BatteryStats.java revision cbefd8dd2befcb768f911a63becc427ec4c13250
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import java.io.PrintWriter;
20import java.util.ArrayList;
21import java.util.Collections;
22import java.util.Comparator;
23import java.util.Formatter;
24import java.util.HashMap;
25import java.util.List;
26import java.util.Map;
27
28import android.content.Context;
29import android.content.pm.ApplicationInfo;
30import android.telephony.SignalStrength;
31import android.text.format.DateFormat;
32import android.util.Printer;
33import android.util.SparseArray;
34import android.util.SparseIntArray;
35import android.util.TimeUtils;
36import com.android.internal.os.BatterySipper;
37import com.android.internal.os.BatteryStatsHelper;
38
39/**
40 * A class providing access to battery usage statistics, including information on
41 * wakelocks, processes, packages, and services.  All times are represented in microseconds
42 * except where indicated otherwise.
43 * @hide
44 */
45public abstract class BatteryStats implements Parcelable {
46
47    private static final boolean LOCAL_LOGV = false;
48
49    /** @hide */
50    public static final String SERVICE_NAME = "batterystats";
51
52    /**
53     * A constant indicating a partial wake lock timer.
54     */
55    public static final int WAKE_TYPE_PARTIAL = 0;
56
57    /**
58     * A constant indicating a full wake lock timer.
59     */
60    public static final int WAKE_TYPE_FULL = 1;
61
62    /**
63     * A constant indicating a window wake lock timer.
64     */
65    public static final int WAKE_TYPE_WINDOW = 2;
66
67    /**
68     * A constant indicating a sensor timer.
69     */
70    public static final int SENSOR = 3;
71
72    /**
73     * A constant indicating a a wifi running timer
74     */
75    public static final int WIFI_RUNNING = 4;
76
77    /**
78     * A constant indicating a full wifi lock timer
79     */
80    public static final int FULL_WIFI_LOCK = 5;
81
82    /**
83     * A constant indicating a wifi scan
84     */
85    public static final int WIFI_SCAN = 6;
86
87     /**
88      * A constant indicating a wifi multicast timer
89      */
90     public static final int WIFI_MULTICAST_ENABLED = 7;
91
92    /**
93     * A constant indicating an audio turn on timer
94     */
95    public static final int AUDIO_TURNED_ON = 7;
96
97    /**
98     * A constant indicating a video turn on timer
99     */
100    public static final int VIDEO_TURNED_ON = 8;
101
102    /**
103     * A constant indicating a vibrator on timer
104     */
105    public static final int VIBRATOR_ON = 9;
106
107    /**
108     * A constant indicating a foreground activity timer
109     */
110    public static final int FOREGROUND_ACTIVITY = 10;
111
112    /**
113     * A constant indicating a wifi batched scan is active
114     */
115    public static final int WIFI_BATCHED_SCAN = 11;
116
117    /**
118     * Include all of the data in the stats, including previously saved data.
119     */
120    public static final int STATS_SINCE_CHARGED = 0;
121
122    /**
123     * Include only the current run in the stats.
124     */
125    public static final int STATS_CURRENT = 1;
126
127    /**
128     * Include only the run since the last time the device was unplugged in the stats.
129     */
130    public static final int STATS_SINCE_UNPLUGGED = 2;
131
132    // NOTE: Update this list if you add/change any stats above.
133    // These characters are supposed to represent "total", "last", "current",
134    // and "unplugged". They were shortened for efficiency sake.
135    private static final String[] STAT_NAMES = { "l", "c", "u" };
136
137    /**
138     * Bump the version on this if the checkin format changes.
139     */
140    private static final int BATTERY_STATS_CHECKIN_VERSION = 8;
141
142    private static final long BYTES_PER_KB = 1024;
143    private static final long BYTES_PER_MB = 1048576; // 1024^2
144    private static final long BYTES_PER_GB = 1073741824; //1024^3
145
146
147    private static final String UID_DATA = "uid";
148    private static final String APK_DATA = "apk";
149    private static final String PROCESS_DATA = "pr";
150    private static final String SENSOR_DATA = "sr";
151    private static final String VIBRATOR_DATA = "vib";
152    private static final String FOREGROUND_DATA = "fg";
153    private static final String WAKELOCK_DATA = "wl";
154    private static final String KERNEL_WAKELOCK_DATA = "kwl";
155    private static final String WAKEUP_REASON_DATA = "wr";
156    private static final String NETWORK_DATA = "nt";
157    private static final String USER_ACTIVITY_DATA = "ua";
158    private static final String BATTERY_DATA = "bt";
159    private static final String BATTERY_DISCHARGE_DATA = "dc";
160    private static final String BATTERY_LEVEL_DATA = "lv";
161    private static final String WIFI_DATA = "wfl";
162    private static final String MISC_DATA = "m";
163    private static final String GLOBAL_NETWORK_DATA = "gn";
164    private static final String HISTORY_STRING_POOL = "hsp";
165    private static final String HISTORY_DATA = "h";
166    private static final String SCREEN_BRIGHTNESS_DATA = "br";
167    private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
168    private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
169    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
170    private static final String DATA_CONNECTION_TIME_DATA = "dct";
171    private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
172    private static final String WIFI_STATE_TIME_DATA = "wst";
173    private static final String WIFI_STATE_COUNT_DATA = "wsc";
174    private static final String BLUETOOTH_STATE_TIME_DATA = "bst";
175    private static final String BLUETOOTH_STATE_COUNT_DATA = "bsc";
176    private static final String POWER_USE_SUMMARY_DATA = "pws";
177    private static final String POWER_USE_ITEM_DATA = "pwi";
178    private static final String DISCHARGE_STEP_DATA = "dsd";
179    private static final String CHARGE_STEP_DATA = "csd";
180    private static final String DISCHARGE_TIME_REMAIN_DATA = "dtr";
181    private static final String CHARGE_TIME_REMAIN_DATA = "ctr";
182
183    private final StringBuilder mFormatBuilder = new StringBuilder(32);
184    private final Formatter mFormatter = new Formatter(mFormatBuilder);
185
186    /**
187     * State for keeping track of counting information.
188     */
189    public static abstract class Counter {
190
191        /**
192         * Returns the count associated with this Counter for the
193         * selected type of statistics.
194         *
195         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
196         */
197        public abstract int getCountLocked(int which);
198
199        /**
200         * Temporary for debugging.
201         */
202        public abstract void logState(Printer pw, String prefix);
203    }
204
205    /**
206     * State for keeping track of long counting information.
207     */
208    public static abstract class LongCounter {
209
210        /**
211         * Returns the count associated with this Counter for the
212         * selected type of statistics.
213         *
214         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
215         */
216        public abstract long getCountLocked(int which);
217
218        /**
219         * Temporary for debugging.
220         */
221        public abstract void logState(Printer pw, String prefix);
222    }
223
224    /**
225     * State for keeping track of timing information.
226     */
227    public static abstract class Timer {
228
229        /**
230         * Returns the count associated with this Timer for the
231         * selected type of statistics.
232         *
233         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
234         */
235        public abstract int getCountLocked(int which);
236
237        /**
238         * Returns the total time in microseconds associated with this Timer for the
239         * selected type of statistics.
240         *
241         * @param elapsedRealtimeUs current elapsed realtime of system in microseconds
242         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
243         * @return a time in microseconds
244         */
245        public abstract long getTotalTimeLocked(long elapsedRealtimeUs, int which);
246
247        /**
248         * Temporary for debugging.
249         */
250        public abstract void logState(Printer pw, String prefix);
251    }
252
253    /**
254     * The statistics associated with a particular uid.
255     */
256    public static abstract class Uid {
257
258        /**
259         * Returns a mapping containing wakelock statistics.
260         *
261         * @return a Map from Strings to Uid.Wakelock objects.
262         */
263        public abstract Map<String, ? extends Wakelock> getWakelockStats();
264
265        /**
266         * The statistics associated with a particular wake lock.
267         */
268        public static abstract class Wakelock {
269            public abstract Timer getWakeTime(int type);
270        }
271
272        /**
273         * Returns a mapping containing sensor statistics.
274         *
275         * @return a Map from Integer sensor ids to Uid.Sensor objects.
276         */
277        public abstract Map<Integer, ? extends Sensor> getSensorStats();
278
279        /**
280         * Returns a mapping containing active process data.
281         */
282        public abstract SparseArray<? extends Pid> getPidStats();
283
284        /**
285         * Returns a mapping containing process statistics.
286         *
287         * @return a Map from Strings to Uid.Proc objects.
288         */
289        public abstract Map<String, ? extends Proc> getProcessStats();
290
291        /**
292         * Returns a mapping containing package statistics.
293         *
294         * @return a Map from Strings to Uid.Pkg objects.
295         */
296        public abstract Map<String, ? extends Pkg> getPackageStats();
297
298        /**
299         * {@hide}
300         */
301        public abstract int getUid();
302
303        public abstract void noteWifiRunningLocked(long elapsedRealtime);
304        public abstract void noteWifiStoppedLocked(long elapsedRealtime);
305        public abstract void noteFullWifiLockAcquiredLocked(long elapsedRealtime);
306        public abstract void noteFullWifiLockReleasedLocked(long elapsedRealtime);
307        public abstract void noteWifiScanStartedLocked(long elapsedRealtime);
308        public abstract void noteWifiScanStoppedLocked(long elapsedRealtime);
309        public abstract void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtime);
310        public abstract void noteWifiBatchedScanStoppedLocked(long elapsedRealtime);
311        public abstract void noteWifiMulticastEnabledLocked(long elapsedRealtime);
312        public abstract void noteWifiMulticastDisabledLocked(long elapsedRealtime);
313        public abstract void noteAudioTurnedOnLocked(long elapsedRealtime);
314        public abstract void noteAudioTurnedOffLocked(long elapsedRealtime);
315        public abstract void noteVideoTurnedOnLocked(long elapsedRealtime);
316        public abstract void noteVideoTurnedOffLocked(long elapsedRealtime);
317        public abstract void noteActivityResumedLocked(long elapsedRealtime);
318        public abstract void noteActivityPausedLocked(long elapsedRealtime);
319        public abstract long getWifiRunningTime(long elapsedRealtimeUs, int which);
320        public abstract long getFullWifiLockTime(long elapsedRealtimeUs, int which);
321        public abstract long getWifiScanTime(long elapsedRealtimeUs, int which);
322        public abstract long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which);
323        public abstract long getWifiMulticastTime(long elapsedRealtimeUs, int which);
324        public abstract long getAudioTurnedOnTime(long elapsedRealtimeUs, int which);
325        public abstract long getVideoTurnedOnTime(long elapsedRealtimeUs, int which);
326        public abstract Timer getForegroundActivityTimer();
327        public abstract Timer getVibratorOnTimer();
328
329        public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5;
330
331        /**
332         * Note that these must match the constants in android.os.PowerManager.
333         * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
334         * also be bumped.
335         */
336        static final String[] USER_ACTIVITY_TYPES = {
337            "other", "button", "touch"
338        };
339
340        public static final int NUM_USER_ACTIVITY_TYPES = 3;
341
342        public abstract void noteUserActivityLocked(int type);
343        public abstract boolean hasUserActivity();
344        public abstract int getUserActivityCount(int type, int which);
345
346        public abstract boolean hasNetworkActivity();
347        public abstract long getNetworkActivityBytes(int type, int which);
348        public abstract long getNetworkActivityPackets(int type, int which);
349        public abstract long getMobileRadioActiveTime(int which);
350        public abstract int getMobileRadioActiveCount(int which);
351
352        public static abstract class Sensor {
353            /*
354             * FIXME: it's not correct to use this magic value because it
355             * could clash with a sensor handle (which are defined by
356             * the sensor HAL, and therefore out of our control
357             */
358            // Magic sensor number for the GPS.
359            public static final int GPS = -10000;
360
361            public abstract int getHandle();
362
363            public abstract Timer getSensorTime();
364        }
365
366        public class Pid {
367            public int mWakeNesting;
368            public long mWakeSumMs;
369            public long mWakeStartMs;
370        }
371
372        /**
373         * The statistics associated with a particular process.
374         */
375        public static abstract class Proc {
376
377            public static class ExcessivePower {
378                public static final int TYPE_WAKE = 1;
379                public static final int TYPE_CPU = 2;
380
381                public int type;
382                public long overTime;
383                public long usedTime;
384            }
385
386            /**
387             * Returns true if this process is still active in the battery stats.
388             */
389            public abstract boolean isActive();
390
391            /**
392             * Returns the total time (in 1/100 sec) spent executing in user code.
393             *
394             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
395             */
396            public abstract long getUserTime(int which);
397
398            /**
399             * Returns the total time (in 1/100 sec) spent executing in system code.
400             *
401             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
402             */
403            public abstract long getSystemTime(int which);
404
405            /**
406             * Returns the number of times the process has been started.
407             *
408             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
409             */
410            public abstract int getStarts(int which);
411
412            /**
413             * Returns the cpu time spent in microseconds while the process was in the foreground.
414             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
415             * @return foreground cpu time in microseconds
416             */
417            public abstract long getForegroundTime(int which);
418
419            /**
420             * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
421             * @param speedStep the index of the CPU speed. This is not the actual speed of the
422             * CPU.
423             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
424             * @see BatteryStats#getCpuSpeedSteps()
425             */
426            public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
427
428            public abstract int countExcessivePowers();
429
430            public abstract ExcessivePower getExcessivePower(int i);
431        }
432
433        /**
434         * The statistics associated with a particular package.
435         */
436        public static abstract class Pkg {
437
438            /**
439             * Returns the number of times this package has done something that could wake up the
440             * device from sleep.
441             *
442             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
443             */
444            public abstract int getWakeups(int which);
445
446            /**
447             * Returns a mapping containing service statistics.
448             */
449            public abstract Map<String, ? extends Serv> getServiceStats();
450
451            /**
452             * The statistics associated with a particular service.
453             */
454            public abstract class Serv {
455
456                /**
457                 * Returns the amount of time spent started.
458                 *
459                 * @param batteryUptime elapsed uptime on battery in microseconds.
460                 * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
461                 * @return
462                 */
463                public abstract long getStartTime(long batteryUptime, int which);
464
465                /**
466                 * Returns the total number of times startService() has been called.
467                 *
468                 * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
469                 */
470                public abstract int getStarts(int which);
471
472                /**
473                 * Returns the total number times the service has been launched.
474                 *
475                 * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
476                 */
477                public abstract int getLaunches(int which);
478            }
479        }
480    }
481
482    public final static class HistoryTag {
483        public String string;
484        public int uid;
485
486        public int poolIdx;
487
488        public void setTo(HistoryTag o) {
489            string = o.string;
490            uid = o.uid;
491            poolIdx = o.poolIdx;
492        }
493
494        public void setTo(String _string, int _uid) {
495            string = _string;
496            uid = _uid;
497            poolIdx = -1;
498        }
499
500        public void writeToParcel(Parcel dest, int flags) {
501            dest.writeString(string);
502            dest.writeInt(uid);
503        }
504
505        public void readFromParcel(Parcel src) {
506            string = src.readString();
507            uid = src.readInt();
508            poolIdx = -1;
509        }
510
511        @Override
512        public boolean equals(Object o) {
513            if (this == o) return true;
514            if (o == null || getClass() != o.getClass()) return false;
515
516            HistoryTag that = (HistoryTag) o;
517
518            if (uid != that.uid) return false;
519            if (!string.equals(that.string)) return false;
520
521            return true;
522        }
523
524        @Override
525        public int hashCode() {
526            int result = string.hashCode();
527            result = 31 * result + uid;
528            return result;
529        }
530    }
531
532    public final static class HistoryItem implements Parcelable {
533        public HistoryItem next;
534
535        public long time;
536
537        public static final byte CMD_UPDATE = 0;        // These can be written as deltas
538        public static final byte CMD_NULL = -1;
539        public static final byte CMD_START = 4;
540        public static final byte CMD_CURRENT_TIME = 5;
541        public static final byte CMD_OVERFLOW = 6;
542        public static final byte CMD_RESET = 7;
543
544        public byte cmd = CMD_NULL;
545
546        /**
547         * Return whether the command code is a delta data update.
548         */
549        public boolean isDeltaData() {
550            return cmd == CMD_UPDATE;
551        }
552
553        public byte batteryLevel;
554        public byte batteryStatus;
555        public byte batteryHealth;
556        public byte batteryPlugType;
557
558        public short batteryTemperature;
559        public char batteryVoltage;
560
561        // Constants from SCREEN_BRIGHTNESS_*
562        public static final int STATE_BRIGHTNESS_SHIFT = 0;
563        public static final int STATE_BRIGHTNESS_MASK = 0x7;
564        // Constants from SIGNAL_STRENGTH_*
565        public static final int STATE_SIGNAL_STRENGTH_SHIFT = 3;
566        public static final int STATE_SIGNAL_STRENGTH_MASK = 0x7 << STATE_SIGNAL_STRENGTH_SHIFT;
567        // Constants from ServiceState.STATE_*
568        public static final int STATE_PHONE_STATE_SHIFT = 6;
569        public static final int STATE_PHONE_STATE_MASK = 0x7 << STATE_PHONE_STATE_SHIFT;
570        // Constants from DATA_CONNECTION_*
571        public static final int STATE_DATA_CONNECTION_SHIFT = 9;
572        public static final int STATE_DATA_CONNECTION_MASK = 0x1f << STATE_DATA_CONNECTION_SHIFT;
573
574        // These states always appear directly in the first int token
575        // of a delta change; they should be ones that change relatively
576        // frequently.
577        public static final int STATE_CPU_RUNNING_FLAG = 1<<31;
578        public static final int STATE_WAKE_LOCK_FLAG = 1<<30;
579        public static final int STATE_GPS_ON_FLAG = 1<<29;
580        public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<28;
581        public static final int STATE_WIFI_SCAN_FLAG = 1<<27;
582        public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<26;
583        public static final int STATE_MOBILE_RADIO_ACTIVE_FLAG = 1<<25;
584        public static final int STATE_WIFI_RUNNING_FLAG = 1<<24;
585        // These are on the lower bits used for the command; if they change
586        // we need to write another int of data.
587        public static final int STATE_SENSOR_ON_FLAG = 1<<23;
588        public static final int STATE_AUDIO_ON_FLAG = 1<<22;
589        public static final int STATE_PHONE_SCANNING_FLAG = 1<<21;
590        public static final int STATE_SCREEN_ON_FLAG = 1<<20;
591        public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<19;
592        public static final int STATE_PHONE_IN_CALL_FLAG = 1<<18;
593        public static final int STATE_WIFI_ON_FLAG = 1<<17;
594        public static final int STATE_BLUETOOTH_ON_FLAG = 1<<16;
595
596        public static final int MOST_INTERESTING_STATES =
597            STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
598            | STATE_GPS_ON_FLAG | STATE_PHONE_IN_CALL_FLAG;
599
600        public int states;
601
602        public static final int STATE2_VIDEO_ON_FLAG = 1<<0;
603        public static final int STATE2_LOW_POWER_FLAG = 1<<1;
604        public int states2;
605
606        // The wake lock that was acquired at this point.
607        public HistoryTag wakelockTag;
608
609        // Kernel wakeup reason at this point.
610        public HistoryTag wakeReasonTag;
611
612        public static final int EVENT_FLAG_START = 0x8000;
613        public static final int EVENT_FLAG_FINISH = 0x4000;
614
615        // No event in this item.
616        public static final int EVENT_NONE = 0x0000;
617        // Event is about a process that is running.
618        public static final int EVENT_PROC = 0x0001;
619        // Event is about an application package that is in the foreground.
620        public static final int EVENT_FOREGROUND = 0x0002;
621        // Event is about an application package that is at the top of the screen.
622        public static final int EVENT_TOP = 0x0003;
623        // Event is about an application package that is at the top of the screen.
624        public static final int EVENT_SYNC = 0x0004;
625        // Events for all additional wake locks aquired/release within a wake block.
626        // These are not generated by default.
627        public static final int EVENT_WAKE_LOCK = 0x0005;
628        // Number of event types.
629        public static final int EVENT_COUNT = 0x0006;
630        // Mask to extract out only the type part of the event.
631        public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
632
633        public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START;
634        public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH;
635        public static final int EVENT_FOREGROUND_START = EVENT_FOREGROUND | EVENT_FLAG_START;
636        public static final int EVENT_FOREGROUND_FINISH = EVENT_FOREGROUND | EVENT_FLAG_FINISH;
637        public static final int EVENT_TOP_START = EVENT_TOP | EVENT_FLAG_START;
638        public static final int EVENT_TOP_FINISH = EVENT_TOP | EVENT_FLAG_FINISH;
639        public static final int EVENT_SYNC_START = EVENT_SYNC | EVENT_FLAG_START;
640        public static final int EVENT_SYNC_FINISH = EVENT_SYNC | EVENT_FLAG_FINISH;
641        public static final int EVENT_WAKE_LOCK_START = EVENT_WAKE_LOCK | EVENT_FLAG_START;
642        public static final int EVENT_WAKE_LOCK_FINISH = EVENT_WAKE_LOCK | EVENT_FLAG_FINISH;
643
644        // For CMD_EVENT.
645        public int eventCode;
646        public HistoryTag eventTag;
647
648        // Only set for CMD_CURRENT_TIME.
649        public long currentTime;
650
651        // Meta-data when reading.
652        public int numReadInts;
653
654        // Pre-allocated objects.
655        public final HistoryTag localWakelockTag = new HistoryTag();
656        public final HistoryTag localWakeReasonTag = new HistoryTag();
657        public final HistoryTag localEventTag = new HistoryTag();
658
659        public HistoryItem() {
660        }
661
662        public HistoryItem(long time, Parcel src) {
663            this.time = time;
664            numReadInts = 2;
665            readFromParcel(src);
666        }
667
668        public int describeContents() {
669            return 0;
670        }
671
672        public void writeToParcel(Parcel dest, int flags) {
673            dest.writeLong(time);
674            int bat = (((int)cmd)&0xff)
675                    | ((((int)batteryLevel)<<8)&0xff00)
676                    | ((((int)batteryStatus)<<16)&0xf0000)
677                    | ((((int)batteryHealth)<<20)&0xf00000)
678                    | ((((int)batteryPlugType)<<24)&0xf000000)
679                    | (wakelockTag != null ? 0x10000000 : 0)
680                    | (wakeReasonTag != null ? 0x20000000 : 0)
681                    | (eventCode != EVENT_NONE ? 0x40000000 : 0);
682            dest.writeInt(bat);
683            bat = (((int)batteryTemperature)&0xffff)
684                    | ((((int)batteryVoltage)<<16)&0xffff0000);
685            dest.writeInt(bat);
686            dest.writeInt(states);
687            dest.writeInt(states2);
688            if (wakelockTag != null) {
689                wakelockTag.writeToParcel(dest, flags);
690            }
691            if (wakeReasonTag != null) {
692                wakeReasonTag.writeToParcel(dest, flags);
693            }
694            if (eventCode != EVENT_NONE) {
695                dest.writeInt(eventCode);
696                eventTag.writeToParcel(dest, flags);
697            }
698            if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
699                dest.writeLong(currentTime);
700            }
701        }
702
703        public void readFromParcel(Parcel src) {
704            int start = src.dataPosition();
705            int bat = src.readInt();
706            cmd = (byte)(bat&0xff);
707            batteryLevel = (byte)((bat>>8)&0xff);
708            batteryStatus = (byte)((bat>>16)&0xf);
709            batteryHealth = (byte)((bat>>20)&0xf);
710            batteryPlugType = (byte)((bat>>24)&0xf);
711            int bat2 = src.readInt();
712            batteryTemperature = (short)(bat2&0xffff);
713            batteryVoltage = (char)((bat2>>16)&0xffff);
714            states = src.readInt();
715            states2 = src.readInt();
716            if ((bat&0x10000000) != 0) {
717                wakelockTag = localWakelockTag;
718                wakelockTag.readFromParcel(src);
719            } else {
720                wakelockTag = null;
721            }
722            if ((bat&0x20000000) != 0) {
723                wakeReasonTag = localWakeReasonTag;
724                wakeReasonTag.readFromParcel(src);
725            } else {
726                wakeReasonTag = null;
727            }
728            if ((bat&0x40000000) != 0) {
729                eventCode = src.readInt();
730                eventTag = localEventTag;
731                eventTag.readFromParcel(src);
732            } else {
733                eventCode = EVENT_NONE;
734                eventTag = null;
735            }
736            if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
737                currentTime = src.readLong();
738            } else {
739                currentTime = 0;
740            }
741            numReadInts += (src.dataPosition()-start)/4;
742        }
743
744        public void clear() {
745            time = 0;
746            cmd = CMD_NULL;
747            batteryLevel = 0;
748            batteryStatus = 0;
749            batteryHealth = 0;
750            batteryPlugType = 0;
751            batteryTemperature = 0;
752            batteryVoltage = 0;
753            states = 0;
754            states2 = 0;
755            wakelockTag = null;
756            wakeReasonTag = null;
757            eventCode = EVENT_NONE;
758            eventTag = null;
759        }
760
761        public void setTo(HistoryItem o) {
762            time = o.time;
763            cmd = o.cmd;
764            setToCommon(o);
765        }
766
767        public void setTo(long time, byte cmd, HistoryItem o) {
768            this.time = time;
769            this.cmd = cmd;
770            setToCommon(o);
771        }
772
773        private void setToCommon(HistoryItem o) {
774            batteryLevel = o.batteryLevel;
775            batteryStatus = o.batteryStatus;
776            batteryHealth = o.batteryHealth;
777            batteryPlugType = o.batteryPlugType;
778            batteryTemperature = o.batteryTemperature;
779            batteryVoltage = o.batteryVoltage;
780            states = o.states;
781            states2 = o.states2;
782            if (o.wakelockTag != null) {
783                wakelockTag = localWakelockTag;
784                wakelockTag.setTo(o.wakelockTag);
785            } else {
786                wakelockTag = null;
787            }
788            if (o.wakeReasonTag != null) {
789                wakeReasonTag = localWakeReasonTag;
790                wakeReasonTag.setTo(o.wakeReasonTag);
791            } else {
792                wakeReasonTag = null;
793            }
794            eventCode = o.eventCode;
795            if (o.eventTag != null) {
796                eventTag = localEventTag;
797                eventTag.setTo(o.eventTag);
798            } else {
799                eventTag = null;
800            }
801            currentTime = o.currentTime;
802        }
803
804        public boolean sameNonEvent(HistoryItem o) {
805            return batteryLevel == o.batteryLevel
806                    && batteryStatus == o.batteryStatus
807                    && batteryHealth == o.batteryHealth
808                    && batteryPlugType == o.batteryPlugType
809                    && batteryTemperature == o.batteryTemperature
810                    && batteryVoltage == o.batteryVoltage
811                    && states == o.states
812                    && states2 == o.states2
813                    && currentTime == o.currentTime;
814        }
815
816        public boolean same(HistoryItem o) {
817            if (!sameNonEvent(o) || eventCode != o.eventCode) {
818                return false;
819            }
820            if (wakelockTag != o.wakelockTag) {
821                if (wakelockTag == null || o.wakelockTag == null) {
822                    return false;
823                }
824                if (!wakelockTag.equals(o.wakelockTag)) {
825                    return false;
826                }
827            }
828            if (wakeReasonTag != o.wakeReasonTag) {
829                if (wakeReasonTag == null || o.wakeReasonTag == null) {
830                    return false;
831                }
832                if (!wakeReasonTag.equals(o.wakeReasonTag)) {
833                    return false;
834                }
835            }
836            if (eventTag != o.eventTag) {
837                if (eventTag == null || o.eventTag == null) {
838                    return false;
839                }
840                if (!eventTag.equals(o.eventTag)) {
841                    return false;
842                }
843            }
844            return true;
845        }
846    }
847
848    public final static class HistoryEventTracker {
849        private final HashMap<String, SparseIntArray>[] mActiveEvents
850                = (HashMap<String, SparseIntArray>[]) new HashMap[HistoryItem.EVENT_COUNT];
851
852        public boolean updateState(int code, String name, int uid, int poolIdx) {
853            if ((code&HistoryItem.EVENT_FLAG_START) != 0) {
854                int idx = code&HistoryItem.EVENT_TYPE_MASK;
855                HashMap<String, SparseIntArray> active = mActiveEvents[idx];
856                if (active == null) {
857                    active = new HashMap<String, SparseIntArray>();
858                    mActiveEvents[idx] = active;
859                }
860                SparseIntArray uids = active.get(name);
861                if (uids == null) {
862                    uids = new SparseIntArray();
863                    active.put(name, uids);
864                }
865                if (uids.indexOfKey(uid) >= 0) {
866                    // Already set, nothing to do!
867                    return false;
868                }
869                uids.put(uid, poolIdx);
870            } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) {
871                int idx = code&HistoryItem.EVENT_TYPE_MASK;
872                HashMap<String, SparseIntArray> active = mActiveEvents[idx];
873                if (active == null) {
874                    // not currently active, nothing to do.
875                    return false;
876                }
877                SparseIntArray uids = active.get(name);
878                if (uids == null) {
879                    // not currently active, nothing to do.
880                    return false;
881                }
882                idx = uids.indexOfKey(uid);
883                if (idx < 0) {
884                    // not currently active, nothing to do.
885                    return false;
886                }
887                uids.removeAt(idx);
888                if (uids.size() <= 0) {
889                    active.remove(name);
890                }
891            }
892            return true;
893        }
894
895        public void removeEvents(int code) {
896            int idx = code&HistoryItem.EVENT_TYPE_MASK;
897            mActiveEvents[idx] = null;
898        }
899
900        public HashMap<String, SparseIntArray> getStateForEvent(int code) {
901            return mActiveEvents[code];
902        }
903    }
904
905    public static final class BitDescription {
906        public final int mask;
907        public final int shift;
908        public final String name;
909        public final String shortName;
910        public final String[] values;
911        public final String[] shortValues;
912
913        public BitDescription(int mask, String name, String shortName) {
914            this.mask = mask;
915            this.shift = -1;
916            this.name = name;
917            this.shortName = shortName;
918            this.values = null;
919            this.shortValues = null;
920        }
921
922        public BitDescription(int mask, int shift, String name, String shortName,
923                String[] values, String[] shortValues) {
924            this.mask = mask;
925            this.shift = shift;
926            this.name = name;
927            this.shortName = shortName;
928            this.values = values;
929            this.shortValues = shortValues;
930        }
931    }
932
933    public abstract int getHistoryTotalSize();
934
935    public abstract int getHistoryUsedSize();
936
937    public abstract boolean startIteratingHistoryLocked();
938
939    public abstract int getHistoryStringPoolSize();
940
941    public abstract int getHistoryStringPoolBytes();
942
943    public abstract String getHistoryTagPoolString(int index);
944
945    public abstract int getHistoryTagPoolUid(int index);
946
947    public abstract boolean getNextHistoryLocked(HistoryItem out);
948
949    public abstract void finishIteratingHistoryLocked();
950
951    public abstract boolean startIteratingOldHistoryLocked();
952
953    public abstract boolean getNextOldHistoryLocked(HistoryItem out);
954
955    public abstract void finishIteratingOldHistoryLocked();
956
957    /**
958     * Return the base time offset for the battery history.
959     */
960    public abstract long getHistoryBaseTime();
961
962    /**
963     * Returns the number of times the device has been started.
964     */
965    public abstract int getStartCount();
966
967    /**
968     * Returns the time in microseconds that the screen has been on while the device was
969     * running on battery.
970     *
971     * {@hide}
972     */
973    public abstract long getScreenOnTime(long elapsedRealtimeUs, int which);
974
975    /**
976     * Returns the number of times the screen was turned on.
977     *
978     * {@hide}
979     */
980    public abstract int getScreenOnCount(int which);
981
982    public abstract long getInteractiveTime(long elapsedRealtimeUs, int which);
983
984    public static final int SCREEN_BRIGHTNESS_DARK = 0;
985    public static final int SCREEN_BRIGHTNESS_DIM = 1;
986    public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
987    public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
988    public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
989
990    static final String[] SCREEN_BRIGHTNESS_NAMES = {
991        "dark", "dim", "medium", "light", "bright"
992    };
993
994    static final String[] SCREEN_BRIGHTNESS_SHORT_NAMES = {
995        "0", "1", "2", "3", "4"
996    };
997
998    public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
999
1000    /**
1001     * Returns the time in microseconds that the screen has been on with
1002     * the given brightness
1003     *
1004     * {@hide}
1005     */
1006    public abstract long getScreenBrightnessTime(int brightnessBin,
1007            long elapsedRealtimeUs, int which);
1008
1009    /**
1010     * Returns the time in microseconds that low power mode has been enabled while the device was
1011     * running on battery.
1012     *
1013     * {@hide}
1014     */
1015    public abstract long getLowPowerModeEnabledTime(long elapsedRealtimeUs, int which);
1016
1017    /**
1018     * Returns the number of times that low power mode was enabled.
1019     *
1020     * {@hide}
1021     */
1022    public abstract int getLowPowerModeEnabledCount(int which);
1023
1024    /**
1025     * Returns the time in microseconds that the phone has been on while the device was
1026     * running on battery.
1027     *
1028     * {@hide}
1029     */
1030    public abstract long getPhoneOnTime(long elapsedRealtimeUs, int which);
1031
1032    /**
1033     * Returns the number of times a phone call was activated.
1034     *
1035     * {@hide}
1036     */
1037    public abstract int getPhoneOnCount(int which);
1038
1039    /**
1040     * Returns the time in microseconds that the phone has been running with
1041     * the given signal strength.
1042     *
1043     * {@hide}
1044     */
1045    public abstract long getPhoneSignalStrengthTime(int strengthBin,
1046            long elapsedRealtimeUs, int which);
1047
1048    /**
1049     * Returns the time in microseconds that the phone has been trying to
1050     * acquire a signal.
1051     *
1052     * {@hide}
1053     */
1054    public abstract long getPhoneSignalScanningTime(
1055            long elapsedRealtimeUs, int which);
1056
1057    /**
1058     * Returns the number of times the phone has entered the given signal strength.
1059     *
1060     * {@hide}
1061     */
1062    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
1063
1064    /**
1065     * Returns the time in microseconds that the mobile network has been active
1066     * (in a high power state).
1067     *
1068     * {@hide}
1069     */
1070    public abstract long getMobileRadioActiveTime(long elapsedRealtimeUs, int which);
1071
1072    /**
1073     * Returns the number of times that the mobile network has transitioned to the
1074     * active state.
1075     *
1076     * {@hide}
1077     */
1078    public abstract int getMobileRadioActiveCount(int which);
1079
1080    /**
1081     * Returns the time in microseconds that is the difference between the mobile radio
1082     * time we saw based on the elapsed timestamp when going down vs. the given time stamp
1083     * from the radio.
1084     *
1085     * {@hide}
1086     */
1087    public abstract long getMobileRadioActiveAdjustedTime(int which);
1088
1089    /**
1090     * Returns the time in microseconds that the mobile network has been active
1091     * (in a high power state) but not being able to blame on an app.
1092     *
1093     * {@hide}
1094     */
1095    public abstract long getMobileRadioActiveUnknownTime(int which);
1096
1097    /**
1098     * Return count of number of times radio was up that could not be blamed on apps.
1099     *
1100     * {@hide}
1101     */
1102    public abstract int getMobileRadioActiveUnknownCount(int which);
1103
1104    public static final int DATA_CONNECTION_NONE = 0;
1105    public static final int DATA_CONNECTION_GPRS = 1;
1106    public static final int DATA_CONNECTION_EDGE = 2;
1107    public static final int DATA_CONNECTION_UMTS = 3;
1108    public static final int DATA_CONNECTION_CDMA = 4;
1109    public static final int DATA_CONNECTION_EVDO_0 = 5;
1110    public static final int DATA_CONNECTION_EVDO_A = 6;
1111    public static final int DATA_CONNECTION_1xRTT = 7;
1112    public static final int DATA_CONNECTION_HSDPA = 8;
1113    public static final int DATA_CONNECTION_HSUPA = 9;
1114    public static final int DATA_CONNECTION_HSPA = 10;
1115    public static final int DATA_CONNECTION_IDEN = 11;
1116    public static final int DATA_CONNECTION_EVDO_B = 12;
1117    public static final int DATA_CONNECTION_LTE = 13;
1118    public static final int DATA_CONNECTION_EHRPD = 14;
1119    public static final int DATA_CONNECTION_HSPAP = 15;
1120    public static final int DATA_CONNECTION_OTHER = 16;
1121
1122    static final String[] DATA_CONNECTION_NAMES = {
1123        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
1124        "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
1125        "ehrpd", "hspap", "other"
1126    };
1127
1128    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
1129
1130    /**
1131     * Returns the time in microseconds that the phone has been running with
1132     * the given data connection.
1133     *
1134     * {@hide}
1135     */
1136    public abstract long getPhoneDataConnectionTime(int dataType,
1137            long elapsedRealtimeUs, int which);
1138
1139    /**
1140     * Returns the number of times the phone has entered the given data
1141     * connection type.
1142     *
1143     * {@hide}
1144     */
1145    public abstract int getPhoneDataConnectionCount(int dataType, int which);
1146
1147    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
1148            = new BitDescription[] {
1149        new BitDescription(HistoryItem.STATE_CPU_RUNNING_FLAG, "running", "r"),
1150        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock", "w"),
1151        new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor", "s"),
1152        new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps", "g"),
1153        new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock", "Wl"),
1154        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan", "Ws"),
1155        new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast", "Wm"),
1156        new BitDescription(HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG, "mobile_radio", "Pr"),
1157        new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running", "Wr"),
1158        new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning", "Psc"),
1159        new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio", "a"),
1160        new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen", "S"),
1161        new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged", "BP"),
1162        new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
1163        new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi", "W"),
1164        new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
1165        new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
1166                HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn", "Pcn",
1167                DATA_CONNECTION_NAMES, DATA_CONNECTION_NAMES),
1168        new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
1169                HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state", "Pst",
1170                new String[] {"in", "out", "emergency", "off"},
1171                new String[] {"in", "out", "em", "off"}),
1172        new BitDescription(HistoryItem.STATE_SIGNAL_STRENGTH_MASK,
1173                HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT, "signal_strength", "Pss",
1174                SignalStrength.SIGNAL_STRENGTH_NAMES, new String[] {
1175                    "0", "1", "2", "3", "4"
1176        }),
1177        new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
1178                HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness", "Sb",
1179                SCREEN_BRIGHTNESS_NAMES, SCREEN_BRIGHTNESS_SHORT_NAMES),
1180    };
1181
1182    public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS
1183            = new BitDescription[] {
1184        new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"),
1185        new BitDescription(HistoryItem.STATE2_LOW_POWER_FLAG, "low_power", "lp"),
1186    };
1187
1188    public static final String[] HISTORY_EVENT_NAMES = new String[] {
1189            "null", "proc", "fg", "top", "sync", "wake_lock_in"
1190    };
1191
1192    public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
1193            "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl"
1194    };
1195
1196    /**
1197     * Returns the time in microseconds that wifi has been on while the device was
1198     * running on battery.
1199     *
1200     * {@hide}
1201     */
1202    public abstract long getWifiOnTime(long elapsedRealtimeUs, int which);
1203
1204    /**
1205     * Returns the time in microseconds that wifi has been on and the driver has
1206     * been in the running state while the device was running on battery.
1207     *
1208     * {@hide}
1209     */
1210    public abstract long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which);
1211
1212    public static final int WIFI_STATE_OFF = 0;
1213    public static final int WIFI_STATE_OFF_SCANNING = 1;
1214    public static final int WIFI_STATE_ON_NO_NETWORKS = 2;
1215    public static final int WIFI_STATE_ON_DISCONNECTED = 3;
1216    public static final int WIFI_STATE_ON_CONNECTED_STA = 4;
1217    public static final int WIFI_STATE_ON_CONNECTED_P2P = 5;
1218    public static final int WIFI_STATE_ON_CONNECTED_STA_P2P = 6;
1219    public static final int WIFI_STATE_SOFT_AP = 7;
1220
1221    static final String[] WIFI_STATE_NAMES = {
1222        "off", "scanning", "no_net", "disconn",
1223        "sta", "p2p", "sta_p2p", "soft_ap"
1224    };
1225
1226    public static final int NUM_WIFI_STATES = WIFI_STATE_SOFT_AP+1;
1227
1228    /**
1229     * Returns the time in microseconds that WiFi has been running in the given state.
1230     *
1231     * {@hide}
1232     */
1233    public abstract long getWifiStateTime(int wifiState,
1234            long elapsedRealtimeUs, int which);
1235
1236    /**
1237     * Returns the number of times that WiFi has entered the given state.
1238     *
1239     * {@hide}
1240     */
1241    public abstract int getWifiStateCount(int wifiState, int which);
1242
1243    /**
1244     * Returns the time in microseconds that bluetooth has been on while the device was
1245     * running on battery.
1246     *
1247     * {@hide}
1248     */
1249    public abstract long getBluetoothOnTime(long elapsedRealtimeUs, int which);
1250
1251    public abstract int getBluetoothPingCount();
1252
1253    public static final int BLUETOOTH_STATE_INACTIVE = 0;
1254    public static final int BLUETOOTH_STATE_LOW = 1;
1255    public static final int BLUETOOTH_STATE_MEDIUM = 2;
1256    public static final int BLUETOOTH_STATE_HIGH = 3;
1257
1258    static final String[] BLUETOOTH_STATE_NAMES = {
1259        "inactive", "low", "med", "high"
1260    };
1261
1262    public static final int NUM_BLUETOOTH_STATES = BLUETOOTH_STATE_HIGH +1;
1263
1264    /**
1265     * Returns the time in microseconds that Bluetooth has been running in the
1266     * given active state.
1267     *
1268     * {@hide}
1269     */
1270    public abstract long getBluetoothStateTime(int bluetoothState,
1271            long elapsedRealtimeUs, int which);
1272
1273    /**
1274     * Returns the number of times that Bluetooth has entered the given active state.
1275     *
1276     * {@hide}
1277     */
1278    public abstract int getBluetoothStateCount(int bluetoothState, int which);
1279
1280    public static final int NETWORK_MOBILE_RX_DATA = 0;
1281    public static final int NETWORK_MOBILE_TX_DATA = 1;
1282    public static final int NETWORK_WIFI_RX_DATA = 2;
1283    public static final int NETWORK_WIFI_TX_DATA = 3;
1284
1285    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_DATA + 1;
1286
1287    public abstract long getNetworkActivityBytes(int type, int which);
1288    public abstract long getNetworkActivityPackets(int type, int which);
1289
1290    /**
1291     * Return the wall clock time when battery stats data collection started.
1292     */
1293    public abstract long getStartClockTime();
1294
1295    /**
1296     * Return whether we are currently running on battery.
1297     */
1298    public abstract boolean getIsOnBattery();
1299
1300    /**
1301     * Returns a SparseArray containing the statistics for each uid.
1302     */
1303    public abstract SparseArray<? extends Uid> getUidStats();
1304
1305    /**
1306     * Returns the current battery uptime in microseconds.
1307     *
1308     * @param curTime the amount of elapsed realtime in microseconds.
1309     */
1310    public abstract long getBatteryUptime(long curTime);
1311
1312    /**
1313     * Returns the current battery realtime in microseconds.
1314     *
1315     * @param curTime the amount of elapsed realtime in microseconds.
1316     */
1317    public abstract long getBatteryRealtime(long curTime);
1318
1319    /**
1320     * Returns the battery percentage level at the last time the device was unplugged from power, or
1321     * the last time it booted on battery power.
1322     */
1323    public abstract int getDischargeStartLevel();
1324
1325    /**
1326     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
1327     * returns the level at the last plug event.
1328     */
1329    public abstract int getDischargeCurrentLevel();
1330
1331    /**
1332     * Get the amount the battery has discharged since the stats were
1333     * last reset after charging, as a lower-end approximation.
1334     */
1335    public abstract int getLowDischargeAmountSinceCharge();
1336
1337    /**
1338     * Get the amount the battery has discharged since the stats were
1339     * last reset after charging, as an upper-end approximation.
1340     */
1341    public abstract int getHighDischargeAmountSinceCharge();
1342
1343    /**
1344     * Retrieve the discharge amount over the selected discharge period <var>which</var>.
1345     */
1346    public abstract int getDischargeAmount(int which);
1347
1348    /**
1349     * Get the amount the battery has discharged while the screen was on,
1350     * since the last time power was unplugged.
1351     */
1352    public abstract int getDischargeAmountScreenOn();
1353
1354    /**
1355     * Get the amount the battery has discharged while the screen was on,
1356     * since the last time the device was charged.
1357     */
1358    public abstract int getDischargeAmountScreenOnSinceCharge();
1359
1360    /**
1361     * Get the amount the battery has discharged while the screen was off,
1362     * since the last time power was unplugged.
1363     */
1364    public abstract int getDischargeAmountScreenOff();
1365
1366    /**
1367     * Get the amount the battery has discharged while the screen was off,
1368     * since the last time the device was charged.
1369     */
1370    public abstract int getDischargeAmountScreenOffSinceCharge();
1371
1372    /**
1373     * Returns the total, last, or current battery uptime in microseconds.
1374     *
1375     * @param curTime the elapsed realtime in microseconds.
1376     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1377     */
1378    public abstract long computeBatteryUptime(long curTime, int which);
1379
1380    /**
1381     * Returns the total, last, or current battery realtime in microseconds.
1382     *
1383     * @param curTime the current elapsed realtime in microseconds.
1384     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1385     */
1386    public abstract long computeBatteryRealtime(long curTime, int which);
1387
1388    /**
1389     * Returns the total, last, or current battery screen off uptime in microseconds.
1390     *
1391     * @param curTime the elapsed realtime in microseconds.
1392     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1393     */
1394    public abstract long computeBatteryScreenOffUptime(long curTime, int which);
1395
1396    /**
1397     * Returns the total, last, or current battery screen off realtime in microseconds.
1398     *
1399     * @param curTime the current elapsed realtime in microseconds.
1400     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1401     */
1402    public abstract long computeBatteryScreenOffRealtime(long curTime, int which);
1403
1404    /**
1405     * Returns the total, last, or current uptime in microseconds.
1406     *
1407     * @param curTime the current elapsed realtime in microseconds.
1408     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1409     */
1410    public abstract long computeUptime(long curTime, int which);
1411
1412    /**
1413     * Returns the total, last, or current realtime in microseconds.
1414     *
1415     * @param curTime the current elapsed realtime in microseconds.
1416     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1417     */
1418    public abstract long computeRealtime(long curTime, int which);
1419
1420    /**
1421     * Compute an approximation for how much run time (in microseconds) is remaining on
1422     * the battery.  Returns -1 if no time can be computed: either there is not
1423     * enough current data to make a decision, or the battery is currently
1424     * charging.
1425     *
1426     * @param curTime The current elepsed realtime in microseconds.
1427     */
1428    public abstract long computeBatteryTimeRemaining(long curTime);
1429
1430    /**
1431     * Return the historical number of discharge steps we currently have.
1432     */
1433    public abstract int getNumDischargeStepDurations();
1434
1435    /**
1436     * Return the array of discharge step durations; the number of valid
1437     * items in it is returned by {@link #getNumDischargeStepDurations()}.
1438     * These values are in milliseconds.
1439     */
1440    public abstract long[] getDischargeStepDurationsArray();
1441
1442    /**
1443     * Compute an approximation for how much time (in microseconds) remains until the battery
1444     * is fully charged.  Returns -1 if no time can be computed: either there is not
1445     * enough current data to make a decision, or the battery is currently
1446     * discharging.
1447     *
1448     * @param curTime The current elepsed realtime in microseconds.
1449     */
1450    public abstract long computeChargeTimeRemaining(long curTime);
1451
1452    /**
1453     * Return the historical number of charge steps we currently have.
1454     */
1455    public abstract int getNumChargeStepDurations();
1456
1457    /**
1458     * Return the array of charge step durations; the number of valid
1459     * items in it is returned by {@link #getNumChargeStepDurations()}.
1460     * These values are in milliseconds.
1461     */
1462    public abstract long[] getChargeStepDurationsArray();
1463
1464    public abstract Map<String, ? extends LongCounter> getWakeupReasonStats();
1465
1466    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
1467
1468    /** Returns the number of different speeds that the CPU can run at */
1469    public abstract int getCpuSpeedSteps();
1470
1471    public abstract void writeToParcelWithoutUids(Parcel out, int flags);
1472
1473    private final static void formatTimeRaw(StringBuilder out, long seconds) {
1474        long days = seconds / (60 * 60 * 24);
1475        if (days != 0) {
1476            out.append(days);
1477            out.append("d ");
1478        }
1479        long used = days * 60 * 60 * 24;
1480
1481        long hours = (seconds - used) / (60 * 60);
1482        if (hours != 0 || used != 0) {
1483            out.append(hours);
1484            out.append("h ");
1485        }
1486        used += hours * 60 * 60;
1487
1488        long mins = (seconds-used) / 60;
1489        if (mins != 0 || used != 0) {
1490            out.append(mins);
1491            out.append("m ");
1492        }
1493        used += mins * 60;
1494
1495        if (seconds != 0 || used != 0) {
1496            out.append(seconds-used);
1497            out.append("s ");
1498        }
1499    }
1500
1501    public final static void formatTime(StringBuilder sb, long time) {
1502        long sec = time / 100;
1503        formatTimeRaw(sb, sec);
1504        sb.append((time - (sec * 100)) * 10);
1505        sb.append("ms ");
1506    }
1507
1508    public final static void formatTimeMs(StringBuilder sb, long time) {
1509        long sec = time / 1000;
1510        formatTimeRaw(sb, sec);
1511        sb.append(time - (sec * 1000));
1512        sb.append("ms ");
1513    }
1514
1515    public final static void formatTimeMsNoSpace(StringBuilder sb, long time) {
1516        long sec = time / 1000;
1517        formatTimeRaw(sb, sec);
1518        sb.append(time - (sec * 1000));
1519        sb.append("ms");
1520    }
1521
1522    public final String formatRatioLocked(long num, long den) {
1523        if (den == 0L) {
1524            return "--%";
1525        }
1526        float perc = ((float)num) / ((float)den) * 100;
1527        mFormatBuilder.setLength(0);
1528        mFormatter.format("%.1f%%", perc);
1529        return mFormatBuilder.toString();
1530    }
1531
1532    final String formatBytesLocked(long bytes) {
1533        mFormatBuilder.setLength(0);
1534
1535        if (bytes < BYTES_PER_KB) {
1536            return bytes + "B";
1537        } else if (bytes < BYTES_PER_MB) {
1538            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
1539            return mFormatBuilder.toString();
1540        } else if (bytes < BYTES_PER_GB){
1541            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
1542            return mFormatBuilder.toString();
1543        } else {
1544            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
1545            return mFormatBuilder.toString();
1546        }
1547    }
1548
1549    private static long computeWakeLock(Timer timer, long elapsedRealtimeUs, int which) {
1550        if (timer != null) {
1551            // Convert from microseconds to milliseconds with rounding
1552            long totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
1553            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
1554            return totalTimeMillis;
1555        }
1556        return 0;
1557    }
1558
1559    /**
1560     *
1561     * @param sb a StringBuilder object.
1562     * @param timer a Timer object contining the wakelock times.
1563     * @param elapsedRealtimeUs the current on-battery time in microseconds.
1564     * @param name the name of the wakelock.
1565     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1566     * @param linePrefix a String to be prepended to each line of output.
1567     * @return the line prefix
1568     */
1569    private static final String printWakeLock(StringBuilder sb, Timer timer,
1570            long elapsedRealtimeUs, String name, int which, String linePrefix) {
1571
1572        if (timer != null) {
1573            long totalTimeMillis = computeWakeLock(timer, elapsedRealtimeUs, which);
1574
1575            int count = timer.getCountLocked(which);
1576            if (totalTimeMillis != 0) {
1577                sb.append(linePrefix);
1578                formatTimeMs(sb, totalTimeMillis);
1579                if (name != null) {
1580                    sb.append(name);
1581                    sb.append(' ');
1582                }
1583                sb.append('(');
1584                sb.append(count);
1585                sb.append(" times)");
1586                return ", ";
1587            }
1588        }
1589        return linePrefix;
1590    }
1591
1592    /**
1593     * Checkin version of wakelock printer. Prints simple comma-separated list.
1594     *
1595     * @param sb a StringBuilder object.
1596     * @param timer a Timer object contining the wakelock times.
1597     * @param elapsedRealtimeUs the current time in microseconds.
1598     * @param name the name of the wakelock.
1599     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
1600     * @param linePrefix a String to be prepended to each line of output.
1601     * @return the line prefix
1602     */
1603    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer,
1604            long elapsedRealtimeUs, String name, int which, String linePrefix) {
1605        long totalTimeMicros = 0;
1606        int count = 0;
1607        if (timer != null) {
1608            totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
1609            count = timer.getCountLocked(which);
1610        }
1611        sb.append(linePrefix);
1612        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
1613        sb.append(',');
1614        sb.append(name != null ? name + "," : "");
1615        sb.append(count);
1616        return ",";
1617    }
1618
1619    /**
1620     * Dump a comma-separated line of values for terse checkin mode.
1621     *
1622     * @param pw the PageWriter to dump log to
1623     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
1624     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
1625     * @param args type-dependent data arguments
1626     */
1627    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
1628           Object... args ) {
1629        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
1630        pw.print(uid); pw.print(',');
1631        pw.print(category); pw.print(',');
1632        pw.print(type);
1633
1634        for (Object arg : args) {
1635            pw.print(',');
1636            pw.print(arg);
1637        }
1638        pw.println();
1639    }
1640
1641    /**
1642     * Checkin server version of dump to produce more compact, computer-readable log.
1643     *
1644     * NOTE: all times are expressed in 'ms'.
1645     */
1646    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
1647        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1648        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1649        final long batteryUptime = getBatteryUptime(rawUptime);
1650        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1651        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1652        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
1653        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
1654                which);
1655        final long totalRealtime = computeRealtime(rawRealtime, which);
1656        final long totalUptime = computeUptime(rawUptime, which);
1657        final long screenOnTime = getScreenOnTime(rawRealtime, which);
1658        final long interactiveTime = getInteractiveTime(rawRealtime, which);
1659        final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which);
1660        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
1661        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
1662        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
1663        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
1664
1665        StringBuilder sb = new StringBuilder(128);
1666
1667        SparseArray<? extends Uid> uidStats = getUidStats();
1668        final int NU = uidStats.size();
1669
1670        String category = STAT_NAMES[which];
1671
1672        // Dump "battery" stat
1673        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
1674                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
1675                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
1676                totalRealtime / 1000, totalUptime / 1000,
1677                getStartClockTime(),
1678                whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
1679
1680        // Calculate wakelock times across all uids.
1681        long fullWakeLockTimeTotal = 0;
1682        long partialWakeLockTimeTotal = 0;
1683
1684        for (int iu = 0; iu < NU; iu++) {
1685            Uid u = uidStats.valueAt(iu);
1686
1687            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1688            if (wakelocks.size() > 0) {
1689                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1690                        : wakelocks.entrySet()) {
1691                    Uid.Wakelock wl = ent.getValue();
1692
1693                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1694                    if (fullWakeTimer != null) {
1695                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime,
1696                                which);
1697                    }
1698
1699                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1700                    if (partialWakeTimer != null) {
1701                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
1702                            rawRealtime, which);
1703                    }
1704                }
1705            }
1706        }
1707
1708        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1709        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1710        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1711        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1712        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1713        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1714        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1715        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1716
1717        // Dump network stats
1718        dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
1719                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
1720                mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
1721
1722        // Dump misc stats
1723        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
1724                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
1725                wifiRunningTime / 1000, bluetoothOnTime / 1000,
1726                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
1727                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
1728                0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which),
1729                getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000,
1730                lowPowerModeEnabledTime / 1000);
1731
1732        // Dump screen brightness stats
1733        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
1734        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1735            args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
1736        }
1737        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
1738
1739        // Dump signal strength stats
1740        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1741        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1742            args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
1743        }
1744        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
1745        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
1746                getPhoneSignalScanningTime(rawRealtime, which) / 1000);
1747        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1748            args[i] = getPhoneSignalStrengthCount(i, which);
1749        }
1750        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
1751
1752        // Dump network type stats
1753        args = new Object[NUM_DATA_CONNECTION_TYPES];
1754        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1755            args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000;
1756        }
1757        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
1758        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1759            args[i] = getPhoneDataConnectionCount(i, which);
1760        }
1761        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
1762
1763        // Dump wifi state stats
1764        args = new Object[NUM_WIFI_STATES];
1765        for (int i=0; i<NUM_WIFI_STATES; i++) {
1766            args[i] = getWifiStateTime(i, rawRealtime, which) / 1000;
1767        }
1768        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_TIME_DATA, args);
1769        for (int i=0; i<NUM_WIFI_STATES; i++) {
1770            args[i] = getWifiStateCount(i, which);
1771        }
1772        dumpLine(pw, 0 /* uid */, category, WIFI_STATE_COUNT_DATA, args);
1773
1774        // Dump bluetooth state stats
1775        args = new Object[NUM_BLUETOOTH_STATES];
1776        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
1777            args[i] = getBluetoothStateTime(i, rawRealtime, which) / 1000;
1778        }
1779        dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_TIME_DATA, args);
1780        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
1781            args[i] = getBluetoothStateCount(i, which);
1782        }
1783        dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_COUNT_DATA, args);
1784
1785        if (which == STATS_SINCE_UNPLUGGED) {
1786            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
1787                    getDischargeCurrentLevel());
1788        }
1789
1790        if (which == STATS_SINCE_UNPLUGGED) {
1791            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1792                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1793                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1794                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1795        } else {
1796            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1797                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
1798                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1799        }
1800
1801        if (reqUid < 0) {
1802            Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
1803            if (kernelWakelocks.size() > 0) {
1804                for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
1805                    sb.setLength(0);
1806                    printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
1807                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
1808                            sb.toString());
1809                }
1810            }
1811            Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
1812            if (wakeupReasons.size() > 0) {
1813                for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
1814                    dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
1815                            "\"" + ent.getKey() + "\"", ent.getValue().getCountLocked(which));
1816                }
1817            }
1818        }
1819
1820        BatteryStatsHelper helper = new BatteryStatsHelper(context, false);
1821        helper.create(this);
1822        helper.refreshStats(which, UserHandle.USER_ALL);
1823        List<BatterySipper> sippers = helper.getUsageList();
1824        if (sippers != null && sippers.size() > 0) {
1825            dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
1826                    BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
1827                    BatteryStatsHelper.makemAh(helper.getComputedPower()),
1828                    BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
1829                    BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
1830            for (int i=0; i<sippers.size(); i++) {
1831                BatterySipper bs = sippers.get(i);
1832                int uid = 0;
1833                String label;
1834                switch (bs.drainType) {
1835                    case IDLE:
1836                        label="idle";
1837                        break;
1838                    case CELL:
1839                        label="cell";
1840                        break;
1841                    case PHONE:
1842                        label="phone";
1843                        break;
1844                    case WIFI:
1845                        label="wifi";
1846                        break;
1847                    case BLUETOOTH:
1848                        label="blue";
1849                        break;
1850                    case SCREEN:
1851                        label="scrn";
1852                        break;
1853                    case APP:
1854                        uid = bs.uidObj.getUid();
1855                        label = "uid";
1856                        break;
1857                    case USER:
1858                        uid = UserHandle.getUid(bs.userId, 0);
1859                        label = "user";
1860                        break;
1861                    case UNACCOUNTED:
1862                        label = "unacc";
1863                        break;
1864                    case OVERCOUNTED:
1865                        label = "over";
1866                        break;
1867                    default:
1868                        label = "???";
1869                }
1870                dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
1871                        BatteryStatsHelper.makemAh(bs.value));
1872            }
1873        }
1874
1875        for (int iu = 0; iu < NU; iu++) {
1876            final int uid = uidStats.keyAt(iu);
1877            if (reqUid >= 0 && uid != reqUid) {
1878                continue;
1879            }
1880            Uid u = uidStats.valueAt(iu);
1881            // Dump Network stats per uid, if any
1882            long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
1883            long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
1884            long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
1885            long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
1886            long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
1887            long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
1888            long mobileActiveTime = u.getMobileRadioActiveTime(which);
1889            int mobileActiveCount = u.getMobileRadioActiveCount(which);
1890            long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
1891            long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
1892            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
1893            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
1894            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
1895
1896            if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
1897                    || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
1898                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
1899                dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
1900                        wifiBytesRx, wifiBytesTx,
1901                        mobilePacketsRx, mobilePacketsTx,
1902                        wifiPacketsRx, wifiPacketsTx,
1903                        mobileActiveTime, mobileActiveCount);
1904            }
1905
1906            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1907                    || uidWifiRunningTime != 0) {
1908                dumpLine(pw, uid, category, WIFI_DATA,
1909                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
1910            }
1911
1912            if (u.hasUserActivity()) {
1913                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
1914                boolean hasData = false;
1915                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1916                    int val = u.getUserActivityCount(i, which);
1917                    args[i] = val;
1918                    if (val != 0) hasData = true;
1919                }
1920                if (hasData) {
1921                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
1922                }
1923            }
1924
1925            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1926            if (wakelocks.size() > 0) {
1927                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1928                        : wakelocks.entrySet()) {
1929                    Uid.Wakelock wl = ent.getValue();
1930                    String linePrefix = "";
1931                    sb.setLength(0);
1932                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
1933                            rawRealtime, "f", which, linePrefix);
1934                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
1935                            rawRealtime, "p", which, linePrefix);
1936                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
1937                            rawRealtime, "w", which, linePrefix);
1938
1939                    // Only log if we had at lease one wakelock...
1940                    if (sb.length() > 0) {
1941                        String name = ent.getKey();
1942                        if (name.indexOf(',') >= 0) {
1943                            name = name.replace(',', '_');
1944                        }
1945                        dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
1946                    }
1947                }
1948            }
1949
1950            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1951            if (sensors.size() > 0)  {
1952                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1953                        : sensors.entrySet()) {
1954                    Uid.Sensor se = ent.getValue();
1955                    int sensorNumber = ent.getKey();
1956                    Timer timer = se.getSensorTime();
1957                    if (timer != null) {
1958                        // Convert from microseconds to milliseconds with rounding
1959                        long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
1960                        int count = timer.getCountLocked(which);
1961                        if (totalTime != 0) {
1962                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1963                        }
1964                    }
1965                }
1966            }
1967
1968            Timer vibTimer = u.getVibratorOnTimer();
1969            if (vibTimer != null) {
1970                // Convert from microseconds to milliseconds with rounding
1971                long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
1972                int count = vibTimer.getCountLocked(which);
1973                if (totalTime != 0) {
1974                    dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
1975                }
1976            }
1977
1978            Timer fgTimer = u.getForegroundActivityTimer();
1979            if (fgTimer != null) {
1980                // Convert from microseconds to milliseconds with rounding
1981                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
1982                int count = fgTimer.getCountLocked(which);
1983                if (totalTime != 0) {
1984                    dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
1985                }
1986            }
1987
1988            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1989            if (processStats.size() > 0) {
1990                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1991                        : processStats.entrySet()) {
1992                    Uid.Proc ps = ent.getValue();
1993
1994                    final long userMillis = ps.getUserTime(which) * 10;
1995                    final long systemMillis = ps.getSystemTime(which) * 10;
1996                    final long foregroundMillis = ps.getForegroundTime(which) * 10;
1997                    final long starts = ps.getStarts(which);
1998
1999                    if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
2000                            || starts != 0) {
2001                        dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
2002                                systemMillis, foregroundMillis, starts);
2003                    }
2004                }
2005            }
2006
2007            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2008            if (packageStats.size() > 0) {
2009                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2010                        : packageStats.entrySet()) {
2011
2012                    Uid.Pkg ps = ent.getValue();
2013                    int wakeups = ps.getWakeups(which);
2014                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2015                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2016                            : serviceStats.entrySet()) {
2017                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2018                        long startTime = ss.getStartTime(batteryUptime, which);
2019                        int starts = ss.getStarts(which);
2020                        int launches = ss.getLaunches(which);
2021                        if (startTime != 0 || starts != 0 || launches != 0) {
2022                            dumpLine(pw, uid, category, APK_DATA,
2023                                    wakeups, // wakeup alarms
2024                                    ent.getKey(), // Apk
2025                                    sent.getKey(), // service
2026                                    startTime / 1000, // time spent started, in ms
2027                                    starts,
2028                                    launches);
2029                        }
2030                    }
2031                }
2032            }
2033        }
2034    }
2035
2036    static final class TimerEntry {
2037        final String mName;
2038        final int mId;
2039        final BatteryStats.Timer mTimer;
2040        final long mTime;
2041        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
2042            mName = name;
2043            mId = id;
2044            mTimer = timer;
2045            mTime = time;
2046        }
2047    }
2048
2049    private void printmAh(PrintWriter printer, double power) {
2050        printer.print(BatteryStatsHelper.makemAh(power));
2051    }
2052
2053    @SuppressWarnings("unused")
2054    public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
2055            int reqUid) {
2056        final long rawUptime = SystemClock.uptimeMillis() * 1000;
2057        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
2058        final long batteryUptime = getBatteryUptime(rawUptime);
2059
2060        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
2061        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
2062        final long totalRealtime = computeRealtime(rawRealtime, which);
2063        final long totalUptime = computeUptime(rawUptime, which);
2064        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
2065        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
2066                which);
2067        final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
2068        final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
2069
2070        StringBuilder sb = new StringBuilder(128);
2071
2072        SparseArray<? extends Uid> uidStats = getUidStats();
2073        final int NU = uidStats.size();
2074
2075        sb.setLength(0);
2076        sb.append(prefix);
2077                sb.append("  Time on battery: ");
2078                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
2079                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
2080                sb.append(") realtime, ");
2081                formatTimeMs(sb, whichBatteryUptime / 1000);
2082                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
2083                sb.append(") uptime");
2084        pw.println(sb.toString());
2085        sb.setLength(0);
2086        sb.append(prefix);
2087                sb.append("  Time on battery screen off: ");
2088                formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("(");
2089                sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
2090                sb.append(") realtime, ");
2091                formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
2092                sb.append("(");
2093                sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
2094                sb.append(") uptime");
2095        pw.println(sb.toString());
2096        sb.setLength(0);
2097        sb.append(prefix);
2098                sb.append("  Total run time: ");
2099                formatTimeMs(sb, totalRealtime / 1000);
2100                sb.append("realtime, ");
2101                formatTimeMs(sb, totalUptime / 1000);
2102                sb.append("uptime");
2103        pw.println(sb.toString());
2104        if (batteryTimeRemaining >= 0) {
2105            sb.setLength(0);
2106            sb.append(prefix);
2107                    sb.append("  Battery time remaining: ");
2108                    formatTimeMs(sb, batteryTimeRemaining / 1000);
2109            pw.println(sb.toString());
2110        }
2111        if (chargeTimeRemaining >= 0) {
2112            sb.setLength(0);
2113            sb.append(prefix);
2114                    sb.append("  Charge time remaining: ");
2115                    formatTimeMs(sb, chargeTimeRemaining / 1000);
2116            pw.println(sb.toString());
2117        }
2118        pw.print("  Start clock time: ");
2119        pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
2120
2121        final long screenOnTime = getScreenOnTime(rawRealtime, which);
2122        final long interactiveTime = getInteractiveTime(rawRealtime, which);
2123        final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which);
2124        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
2125        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
2126        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
2127        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
2128        sb.setLength(0);
2129        sb.append(prefix);
2130                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
2131                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
2132                sb.append(") "); sb.append(getScreenOnCount(which));
2133                sb.append("x, Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
2134                sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
2135                sb.append(")");
2136        pw.println(sb.toString());
2137        sb.setLength(0);
2138        sb.append(prefix);
2139        sb.append("  Screen brightnesses:");
2140        boolean didOne = false;
2141        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2142            final long time = getScreenBrightnessTime(i, rawRealtime, which);
2143            if (time == 0) {
2144                continue;
2145            }
2146            sb.append("\n    ");
2147            sb.append(prefix);
2148            didOne = true;
2149            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
2150            sb.append(" ");
2151            formatTimeMs(sb, time/1000);
2152            sb.append("(");
2153            sb.append(formatRatioLocked(time, screenOnTime));
2154            sb.append(")");
2155        }
2156        if (!didOne) sb.append(" (no activity)");
2157        pw.println(sb.toString());
2158        if (lowPowerModeEnabledTime != 0) {
2159            sb.setLength(0);
2160            sb.append(prefix);
2161                    sb.append("  Low power mode enabled: ");
2162                    formatTimeMs(sb, lowPowerModeEnabledTime / 1000);
2163                    sb.append("(");
2164                    sb.append(formatRatioLocked(lowPowerModeEnabledTime, whichBatteryRealtime));
2165                    sb.append(")");
2166            pw.println(sb.toString());
2167        }
2168        if (phoneOnTime != 0) {
2169            sb.setLength(0);
2170            sb.append(prefix);
2171                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
2172                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
2173                    sb.append(") "); sb.append(getPhoneOnCount(which));
2174        }
2175
2176        // Calculate wakelock times across all uids.
2177        long fullWakeLockTimeTotalMicros = 0;
2178        long partialWakeLockTimeTotalMicros = 0;
2179
2180        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
2181
2182        for (int iu = 0; iu < NU; iu++) {
2183            Uid u = uidStats.valueAt(iu);
2184
2185            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
2186            if (wakelocks.size() > 0) {
2187                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
2188                        : wakelocks.entrySet()) {
2189                    Uid.Wakelock wl = ent.getValue();
2190
2191                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
2192                    if (fullWakeTimer != null) {
2193                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
2194                                rawRealtime, which);
2195                    }
2196
2197                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
2198                    if (partialWakeTimer != null) {
2199                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
2200                                rawRealtime, which);
2201                        if (totalTimeMicros > 0) {
2202                            if (reqUid < 0) {
2203                                // Only show the ordered list of all wake
2204                                // locks if the caller is not asking for data
2205                                // about a specific uid.
2206                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
2207                                        partialWakeTimer, totalTimeMicros));
2208                            }
2209                            partialWakeLockTimeTotalMicros += totalTimeMicros;
2210                        }
2211                    }
2212                }
2213            }
2214        }
2215
2216        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2217        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2218        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2219        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2220        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2221        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2222        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2223        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2224
2225        if (fullWakeLockTimeTotalMicros != 0) {
2226            sb.setLength(0);
2227            sb.append(prefix);
2228                    sb.append("  Total full wakelock time: "); formatTimeMsNoSpace(sb,
2229                            (fullWakeLockTimeTotalMicros + 500) / 1000);
2230            pw.println(sb.toString());
2231        }
2232
2233        if (partialWakeLockTimeTotalMicros != 0) {
2234            sb.setLength(0);
2235            sb.append(prefix);
2236                    sb.append("  Total partial wakelock time: "); formatTimeMsNoSpace(sb,
2237                            (partialWakeLockTimeTotalMicros + 500) / 1000);
2238            pw.println(sb.toString());
2239        }
2240
2241        pw.print(prefix);
2242                pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
2243                pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
2244                pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
2245                pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
2246        sb.setLength(0);
2247        sb.append(prefix);
2248        sb.append("  Signal levels:");
2249        didOne = false;
2250        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2251            final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
2252            if (time == 0) {
2253                continue;
2254            }
2255            sb.append("\n    ");
2256            sb.append(prefix);
2257            didOne = true;
2258            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
2259            sb.append(" ");
2260            formatTimeMs(sb, time/1000);
2261            sb.append("(");
2262            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2263            sb.append(") ");
2264            sb.append(getPhoneSignalStrengthCount(i, which));
2265            sb.append("x");
2266        }
2267        if (!didOne) sb.append(" (no activity)");
2268        pw.println(sb.toString());
2269
2270        sb.setLength(0);
2271        sb.append(prefix);
2272        sb.append("  Signal scanning time: ");
2273        formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
2274        pw.println(sb.toString());
2275
2276        sb.setLength(0);
2277        sb.append(prefix);
2278        sb.append("  Radio types:");
2279        didOne = false;
2280        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2281            final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
2282            if (time == 0) {
2283                continue;
2284            }
2285            sb.append("\n    ");
2286            sb.append(prefix);
2287            didOne = true;
2288            sb.append(DATA_CONNECTION_NAMES[i]);
2289            sb.append(" ");
2290            formatTimeMs(sb, time/1000);
2291            sb.append("(");
2292            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2293            sb.append(") ");
2294            sb.append(getPhoneDataConnectionCount(i, which));
2295            sb.append("x");
2296        }
2297        if (!didOne) sb.append(" (no activity)");
2298        pw.println(sb.toString());
2299
2300        sb.setLength(0);
2301        sb.append(prefix);
2302        sb.append("  Mobile radio active time: ");
2303        final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
2304        formatTimeMs(sb, mobileActiveTime / 1000);
2305        sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
2306        sb.append(") "); sb.append(getMobileRadioActiveCount(which));
2307        sb.append("x");
2308        pw.println(sb.toString());
2309
2310        final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
2311        if (mobileActiveUnknownTime != 0) {
2312            sb.setLength(0);
2313            sb.append(prefix);
2314            sb.append("  Mobile radio active unknown time: ");
2315            formatTimeMs(sb, mobileActiveUnknownTime / 1000);
2316            sb.append("(");
2317            sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
2318            sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
2319            sb.append("x");
2320            pw.println(sb.toString());
2321        }
2322
2323        final long mobileActiveAdjustedTime = getMobileRadioActiveAdjustedTime(which);
2324        if (mobileActiveAdjustedTime != 0) {
2325            sb.setLength(0);
2326            sb.append(prefix);
2327            sb.append("  Mobile radio active adjusted time: ");
2328            formatTimeMs(sb, mobileActiveAdjustedTime / 1000);
2329            sb.append("(");
2330            sb.append(formatRatioLocked(mobileActiveAdjustedTime, whichBatteryRealtime));
2331            sb.append(")");
2332            pw.println(sb.toString());
2333        }
2334
2335        pw.print(prefix);
2336                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
2337                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
2338                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
2339                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
2340        sb.setLength(0);
2341        sb.append(prefix);
2342                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
2343                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
2344                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
2345                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
2346                sb.append(")");
2347        pw.println(sb.toString());
2348
2349        sb.setLength(0);
2350        sb.append(prefix);
2351        sb.append("  Wifi states:");
2352        didOne = false;
2353        for (int i=0; i<NUM_WIFI_STATES; i++) {
2354            final long time = getWifiStateTime(i, rawRealtime, which);
2355            if (time == 0) {
2356                continue;
2357            }
2358            sb.append("\n    ");
2359            didOne = true;
2360            sb.append(WIFI_STATE_NAMES[i]);
2361            sb.append(" ");
2362            formatTimeMs(sb, time/1000);
2363            sb.append("(");
2364            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2365            sb.append(") ");
2366            sb.append(getPhoneDataConnectionCount(i, which));
2367            sb.append("x");
2368        }
2369        if (!didOne) sb.append(" (no activity)");
2370        pw.println(sb.toString());
2371
2372        sb.setLength(0);
2373        sb.append(prefix);
2374                sb.append("  Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
2375                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
2376                sb.append(")");
2377        pw.println(sb.toString());
2378
2379        sb.setLength(0);
2380        sb.append(prefix);
2381        sb.append("  Bluetooth states:");
2382        didOne = false;
2383        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
2384            final long time = getBluetoothStateTime(i, rawRealtime, which);
2385            if (time == 0) {
2386                continue;
2387            }
2388            sb.append("\n    ");
2389            didOne = true;
2390            sb.append(BLUETOOTH_STATE_NAMES[i]);
2391            sb.append(" ");
2392            formatTimeMs(sb, time/1000);
2393            sb.append("(");
2394            sb.append(formatRatioLocked(time, whichBatteryRealtime));
2395            sb.append(") ");
2396            sb.append(getPhoneDataConnectionCount(i, which));
2397            sb.append("x");
2398        }
2399        if (!didOne) sb.append(" (no activity)");
2400        pw.println(sb.toString());
2401
2402        pw.println();
2403
2404        if (which == STATS_SINCE_UNPLUGGED) {
2405            if (getIsOnBattery()) {
2406                pw.print(prefix); pw.println("  Device is currently unplugged");
2407                pw.print(prefix); pw.print("    Discharge cycle start level: ");
2408                        pw.println(getDischargeStartLevel());
2409                pw.print(prefix); pw.print("    Discharge cycle current level: ");
2410                        pw.println(getDischargeCurrentLevel());
2411            } else {
2412                pw.print(prefix); pw.println("  Device is currently plugged into power");
2413                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
2414                        pw.println(getDischargeStartLevel());
2415                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
2416                        pw.println(getDischargeCurrentLevel());
2417            }
2418            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
2419                    pw.println(getDischargeAmountScreenOn());
2420            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
2421                    pw.println(getDischargeAmountScreenOff());
2422            pw.println(" ");
2423        } else {
2424            pw.print(prefix); pw.println("  Device battery use since last full charge");
2425            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
2426                    pw.println(getLowDischargeAmountSinceCharge());
2427            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
2428                    pw.println(getHighDischargeAmountSinceCharge());
2429            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
2430                    pw.println(getDischargeAmountScreenOnSinceCharge());
2431            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
2432                    pw.println(getDischargeAmountScreenOffSinceCharge());
2433            pw.println();
2434        }
2435
2436        BatteryStatsHelper helper = new BatteryStatsHelper(context, false);
2437        helper.create(this);
2438        helper.refreshStats(which, UserHandle.USER_ALL);
2439        List<BatterySipper> sippers = helper.getUsageList();
2440        if (sippers != null && sippers.size() > 0) {
2441            pw.print(prefix); pw.println("  Estimated power use (mAh):");
2442            pw.print(prefix); pw.print("    Capacity: ");
2443                    printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
2444                    pw.print(", Computed drain: "); printmAh(pw, helper.getComputedPower());
2445                    pw.print(", Min drain: "); printmAh(pw, helper.getMinDrainedPower());
2446                    pw.print(", Max drain: "); printmAh(pw, helper.getMaxDrainedPower());
2447                    pw.println();
2448            for (int i=0; i<sippers.size(); i++) {
2449                BatterySipper bs = sippers.get(i);
2450                switch (bs.drainType) {
2451                    case IDLE:
2452                        pw.print(prefix); pw.print("    Idle: "); printmAh(pw, bs.value);
2453                        pw.println();
2454                        break;
2455                    case CELL:
2456                        pw.print(prefix); pw.print("    Cell standby: "); printmAh(pw, bs.value);
2457                        pw.println();
2458                        break;
2459                    case PHONE:
2460                        pw.print(prefix); pw.print("    Phone calls: "); printmAh(pw, bs.value);
2461                        pw.println();
2462                        break;
2463                    case WIFI:
2464                        pw.print(prefix); pw.print("    Wifi: "); printmAh(pw, bs.value);
2465                        pw.println();
2466                        break;
2467                    case BLUETOOTH:
2468                        pw.print(prefix); pw.print("    Bluetooth: "); printmAh(pw, bs.value);
2469                        pw.println();
2470                        break;
2471                    case SCREEN:
2472                        pw.print(prefix); pw.print("    Screen: "); printmAh(pw, bs.value);
2473                        pw.println();
2474                        break;
2475                    case APP:
2476                        pw.print(prefix); pw.print("    Uid ");
2477                        UserHandle.formatUid(pw, bs.uidObj.getUid());
2478                        pw.print(": "); printmAh(pw, bs.value); pw.println();
2479                        break;
2480                    case USER:
2481                        pw.print(prefix); pw.print("    User "); pw.print(bs.userId);
2482                        pw.print(": "); printmAh(pw, bs.value); pw.println();
2483                        break;
2484                    case UNACCOUNTED:
2485                        pw.print(prefix); pw.print("    Unaccounted: "); printmAh(pw, bs.value);
2486                        pw.println();
2487                        break;
2488                    case OVERCOUNTED:
2489                        pw.print(prefix); pw.print("    Over-counted: "); printmAh(pw, bs.value);
2490                        pw.println();
2491                        break;
2492                }
2493            }
2494            pw.println();
2495        }
2496
2497        sippers = helper.getMobilemsppList();
2498        if (sippers != null && sippers.size() > 0) {
2499            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
2500            long totalTime = 0;
2501            for (int i=0; i<sippers.size(); i++) {
2502                BatterySipper bs = sippers.get(i);
2503                sb.setLength(0);
2504                sb.append(prefix); sb.append("    Uid ");
2505                UserHandle.formatUid(sb, bs.uidObj.getUid());
2506                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
2507                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
2508                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
2509                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
2510                pw.println(sb.toString());
2511                totalTime += bs.mobileActive;
2512            }
2513            sb.setLength(0);
2514            sb.append(prefix);
2515            sb.append("    TOTAL TIME: ");
2516            formatTimeMs(sb, totalTime);
2517            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
2518            sb.append(")");
2519            pw.println(sb.toString());
2520            pw.println();
2521        }
2522
2523        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
2524            @Override
2525            public int compare(TimerEntry lhs, TimerEntry rhs) {
2526                long lhsTime = lhs.mTime;
2527                long rhsTime = rhs.mTime;
2528                if (lhsTime < rhsTime) {
2529                    return 1;
2530                }
2531                if (lhsTime > rhsTime) {
2532                    return -1;
2533                }
2534                return 0;
2535            }
2536        };
2537
2538        if (reqUid < 0) {
2539            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
2540            if (kernelWakelocks.size() > 0) {
2541                final ArrayList<TimerEntry> ktimers = new ArrayList<TimerEntry>();
2542                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
2543                    BatteryStats.Timer timer = ent.getValue();
2544                    long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
2545                    if (totalTimeMillis > 0) {
2546                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
2547                    }
2548                }
2549                if (ktimers.size() > 0) {
2550                    Collections.sort(ktimers, timerComparator);
2551                    pw.print(prefix); pw.println("  All kernel wake locks:");
2552                    for (int i=0; i<ktimers.size(); i++) {
2553                        TimerEntry timer = ktimers.get(i);
2554                        String linePrefix = ": ";
2555                        sb.setLength(0);
2556                        sb.append(prefix);
2557                        sb.append("  Kernel Wake lock ");
2558                        sb.append(timer.mName);
2559                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
2560                                which, linePrefix);
2561                        if (!linePrefix.equals(": ")) {
2562                            sb.append(" realtime");
2563                            // Only print out wake locks that were held
2564                            pw.println(sb.toString());
2565                        }
2566                    }
2567                    pw.println();
2568                }
2569            }
2570
2571            if (timers.size() > 0) {
2572                Collections.sort(timers, timerComparator);
2573                pw.print(prefix); pw.println("  All partial wake locks:");
2574                for (int i=0; i<timers.size(); i++) {
2575                    TimerEntry timer = timers.get(i);
2576                    sb.setLength(0);
2577                    sb.append("  Wake lock ");
2578                    UserHandle.formatUid(sb, timer.mId);
2579                    sb.append(" ");
2580                    sb.append(timer.mName);
2581                    printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
2582                    sb.append(" realtime");
2583                    pw.println(sb.toString());
2584                }
2585                timers.clear();
2586                pw.println();
2587            }
2588
2589            Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
2590            if (wakeupReasons.size() > 0) {
2591                pw.print(prefix); pw.println("  All wakeup reasons:");
2592                final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>();
2593                for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
2594                    BatteryStats.LongCounter counter = ent.getValue();
2595                    reasons.add(new TimerEntry(ent.getKey(), 0, null,
2596                            ent.getValue().getCountLocked(which)));
2597                }
2598                Collections.sort(reasons, timerComparator);
2599                for (int i=0; i<reasons.size(); i++) {
2600                    TimerEntry timer = reasons.get(i);
2601                    String linePrefix = ": ";
2602                    sb.setLength(0);
2603                    sb.append(prefix);
2604                    sb.append("  Wakeup reason ");
2605                    sb.append(timer.mName);
2606                    sb.append(": ");
2607                    formatTimeMs(sb, timer.mTime);
2608                    sb.append("realtime");
2609                    pw.println(sb.toString());
2610                }
2611                pw.println();
2612            }
2613        }
2614
2615        for (int iu=0; iu<NU; iu++) {
2616            final int uid = uidStats.keyAt(iu);
2617            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
2618                continue;
2619            }
2620
2621            Uid u = uidStats.valueAt(iu);
2622
2623            pw.print(prefix);
2624            pw.print("  ");
2625            UserHandle.formatUid(pw, uid);
2626            pw.println(":");
2627            boolean uidActivity = false;
2628
2629            long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
2630            long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
2631            long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
2632            long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
2633            long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
2634            long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
2635            long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
2636            int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
2637            long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
2638            long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
2639            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
2640            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
2641            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
2642
2643            if (mobileRxBytes > 0 || mobileTxBytes > 0
2644                    || mobileRxPackets > 0 || mobileTxPackets > 0) {
2645                pw.print(prefix); pw.print("    Mobile network: ");
2646                        pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
2647                        pw.print(formatBytesLocked(mobileTxBytes));
2648                        pw.print(" sent (packets "); pw.print(mobileRxPackets);
2649                        pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
2650            }
2651            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
2652                sb.setLength(0);
2653                sb.append(prefix); sb.append("    Mobile radio active: ");
2654                formatTimeMs(sb, uidMobileActiveTime / 1000);
2655                sb.append("(");
2656                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
2657                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
2658                long packets = mobileRxPackets + mobileTxPackets;
2659                if (packets == 0) {
2660                    packets = 1;
2661                }
2662                sb.append(" @ ");
2663                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
2664                sb.append(" mspp");
2665                pw.println(sb.toString());
2666            }
2667
2668            if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
2669                pw.print(prefix); pw.print("    Wi-Fi network: ");
2670                        pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
2671                        pw.print(formatBytesLocked(wifiTxBytes));
2672                        pw.print(" sent (packets "); pw.print(wifiRxPackets);
2673                        pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
2674            }
2675
2676            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
2677                    || uidWifiRunningTime != 0) {
2678                sb.setLength(0);
2679                sb.append(prefix); sb.append("    Wifi Running: ");
2680                        formatTimeMs(sb, uidWifiRunningTime / 1000);
2681                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
2682                                whichBatteryRealtime)); sb.append(")\n");
2683                sb.append(prefix); sb.append("    Full Wifi Lock: ");
2684                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
2685                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
2686                                whichBatteryRealtime)); sb.append(")\n");
2687                sb.append(prefix); sb.append("    Wifi Scan: ");
2688                        formatTimeMs(sb, wifiScanTime / 1000);
2689                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
2690                                whichBatteryRealtime)); sb.append(")");
2691                pw.println(sb.toString());
2692            }
2693
2694            if (u.hasUserActivity()) {
2695                boolean hasData = false;
2696                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2697                    int val = u.getUserActivityCount(i, which);
2698                    if (val != 0) {
2699                        if (!hasData) {
2700                            sb.setLength(0);
2701                            sb.append("    User activity: ");
2702                            hasData = true;
2703                        } else {
2704                            sb.append(", ");
2705                        }
2706                        sb.append(val);
2707                        sb.append(" ");
2708                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
2709                    }
2710                }
2711                if (hasData) {
2712                    pw.println(sb.toString());
2713                }
2714            }
2715
2716            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
2717            if (wakelocks.size() > 0) {
2718                long totalFull = 0, totalPartial = 0, totalWindow = 0;
2719                int count = 0;
2720                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
2721                    : wakelocks.entrySet()) {
2722                    Uid.Wakelock wl = ent.getValue();
2723                    String linePrefix = ": ";
2724                    sb.setLength(0);
2725                    sb.append(prefix);
2726                    sb.append("    Wake lock ");
2727                    sb.append(ent.getKey());
2728                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
2729                            "full", which, linePrefix);
2730                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
2731                            "partial", which, linePrefix);
2732                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
2733                            "window", which, linePrefix);
2734                    if (!linePrefix.equals(": ")) {
2735                        sb.append(" realtime");
2736                        // Only print out wake locks that were held
2737                        pw.println(sb.toString());
2738                        uidActivity = true;
2739                        count++;
2740                    }
2741                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
2742                            rawRealtime, which);
2743                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
2744                            rawRealtime, which);
2745                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
2746                            rawRealtime, which);
2747                }
2748                if (count > 1) {
2749                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
2750                        sb.setLength(0);
2751                        sb.append(prefix);
2752                        sb.append("    TOTAL wake: ");
2753                        boolean needComma = false;
2754                        if (totalFull != 0) {
2755                            needComma = true;
2756                            formatTimeMs(sb, totalFull);
2757                            sb.append("full");
2758                        }
2759                        if (totalPartial != 0) {
2760                            if (needComma) {
2761                                sb.append(", ");
2762                            }
2763                            needComma = true;
2764                            formatTimeMs(sb, totalPartial);
2765                            sb.append("partial");
2766                        }
2767                        if (totalWindow != 0) {
2768                            if (needComma) {
2769                                sb.append(", ");
2770                            }
2771                            needComma = true;
2772                            formatTimeMs(sb, totalWindow);
2773                            sb.append("window");
2774                        }
2775                        sb.append(" realtime");
2776                        pw.println(sb.toString());
2777                    }
2778                }
2779            }
2780
2781            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
2782            if (sensors.size() > 0) {
2783                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
2784                    : sensors.entrySet()) {
2785                    Uid.Sensor se = ent.getValue();
2786                    int sensorNumber = ent.getKey();
2787                    sb.setLength(0);
2788                    sb.append(prefix);
2789                    sb.append("    Sensor ");
2790                    int handle = se.getHandle();
2791                    if (handle == Uid.Sensor.GPS) {
2792                        sb.append("GPS");
2793                    } else {
2794                        sb.append(handle);
2795                    }
2796                    sb.append(": ");
2797
2798                    Timer timer = se.getSensorTime();
2799                    if (timer != null) {
2800                        // Convert from microseconds to milliseconds with rounding
2801                        long totalTime = (timer.getTotalTimeLocked(
2802                                rawRealtime, which) + 500) / 1000;
2803                        int count = timer.getCountLocked(which);
2804                        //timer.logState();
2805                        if (totalTime != 0) {
2806                            formatTimeMs(sb, totalTime);
2807                            sb.append("realtime (");
2808                            sb.append(count);
2809                            sb.append(" times)");
2810                        } else {
2811                            sb.append("(not used)");
2812                        }
2813                    } else {
2814                        sb.append("(not used)");
2815                    }
2816
2817                    pw.println(sb.toString());
2818                    uidActivity = true;
2819                }
2820            }
2821
2822            Timer vibTimer = u.getVibratorOnTimer();
2823            if (vibTimer != null) {
2824                // Convert from microseconds to milliseconds with rounding
2825                long totalTime = (vibTimer.getTotalTimeLocked(
2826                        rawRealtime, which) + 500) / 1000;
2827                int count = vibTimer.getCountLocked(which);
2828                //timer.logState();
2829                if (totalTime != 0) {
2830                    sb.setLength(0);
2831                    sb.append(prefix);
2832                    sb.append("    Vibrator: ");
2833                    formatTimeMs(sb, totalTime);
2834                    sb.append("realtime (");
2835                    sb.append(count);
2836                    sb.append(" times)");
2837                    pw.println(sb.toString());
2838                    uidActivity = true;
2839                }
2840            }
2841
2842            Timer fgTimer = u.getForegroundActivityTimer();
2843            if (fgTimer != null) {
2844                // Convert from microseconds to milliseconds with rounding
2845                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
2846                int count = fgTimer.getCountLocked(which);
2847                if (totalTime != 0) {
2848                    sb.setLength(0);
2849                    sb.append(prefix);
2850                    sb.append("    Foreground activities: ");
2851                    formatTimeMs(sb, totalTime);
2852                    sb.append("realtime (");
2853                    sb.append(count);
2854                    sb.append(" times)");
2855                    pw.println(sb.toString());
2856                    uidActivity = true;
2857                }
2858            }
2859
2860            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
2861            if (processStats.size() > 0) {
2862                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
2863                    : processStats.entrySet()) {
2864                    Uid.Proc ps = ent.getValue();
2865                    long userTime;
2866                    long systemTime;
2867                    long foregroundTime;
2868                    int starts;
2869                    int numExcessive;
2870
2871                    userTime = ps.getUserTime(which);
2872                    systemTime = ps.getSystemTime(which);
2873                    foregroundTime = ps.getForegroundTime(which);
2874                    starts = ps.getStarts(which);
2875                    numExcessive = which == STATS_SINCE_CHARGED
2876                            ? ps.countExcessivePowers() : 0;
2877
2878                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
2879                            || numExcessive != 0) {
2880                        sb.setLength(0);
2881                        sb.append(prefix); sb.append("    Proc ");
2882                                sb.append(ent.getKey()); sb.append(":\n");
2883                        sb.append(prefix); sb.append("      CPU: ");
2884                                formatTime(sb, userTime); sb.append("usr + ");
2885                                formatTime(sb, systemTime); sb.append("krn ; ");
2886                                formatTime(sb, foregroundTime); sb.append("fg");
2887                        if (starts != 0) {
2888                            sb.append("\n"); sb.append(prefix); sb.append("      ");
2889                                    sb.append(starts); sb.append(" proc starts");
2890                        }
2891                        pw.println(sb.toString());
2892                        for (int e=0; e<numExcessive; e++) {
2893                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
2894                            if (ew != null) {
2895                                pw.print(prefix); pw.print("      * Killed for ");
2896                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
2897                                            pw.print("wake lock");
2898                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
2899                                            pw.print("cpu");
2900                                        } else {
2901                                            pw.print("unknown");
2902                                        }
2903                                        pw.print(" use: ");
2904                                        TimeUtils.formatDuration(ew.usedTime, pw);
2905                                        pw.print(" over ");
2906                                        TimeUtils.formatDuration(ew.overTime, pw);
2907                                        if (ew.overTime != 0) {
2908                                            pw.print(" (");
2909                                            pw.print((ew.usedTime*100)/ew.overTime);
2910                                            pw.println("%)");
2911                                        }
2912                            }
2913                        }
2914                        uidActivity = true;
2915                    }
2916                }
2917            }
2918
2919            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2920            if (packageStats.size() > 0) {
2921                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2922                    : packageStats.entrySet()) {
2923                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
2924                    boolean apkActivity = false;
2925                    Uid.Pkg ps = ent.getValue();
2926                    int wakeups = ps.getWakeups(which);
2927                    if (wakeups != 0) {
2928                        pw.print(prefix); pw.print("      ");
2929                                pw.print(wakeups); pw.println(" wakeup alarms");
2930                        apkActivity = true;
2931                    }
2932                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2933                    if (serviceStats.size() > 0) {
2934                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2935                                : serviceStats.entrySet()) {
2936                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2937                            long startTime = ss.getStartTime(batteryUptime, which);
2938                            int starts = ss.getStarts(which);
2939                            int launches = ss.getLaunches(which);
2940                            if (startTime != 0 || starts != 0 || launches != 0) {
2941                                sb.setLength(0);
2942                                sb.append(prefix); sb.append("      Service ");
2943                                        sb.append(sent.getKey()); sb.append(":\n");
2944                                sb.append(prefix); sb.append("        Created for: ");
2945                                        formatTimeMs(sb, startTime / 1000);
2946                                        sb.append("uptime\n");
2947                                sb.append(prefix); sb.append("        Starts: ");
2948                                        sb.append(starts);
2949                                        sb.append(", launches: "); sb.append(launches);
2950                                pw.println(sb.toString());
2951                                apkActivity = true;
2952                            }
2953                        }
2954                    }
2955                    if (!apkActivity) {
2956                        pw.print(prefix); pw.println("      (nothing executed)");
2957                    }
2958                    uidActivity = true;
2959                }
2960            }
2961            if (!uidActivity) {
2962                pw.print(prefix); pw.println("    (nothing executed)");
2963            }
2964        }
2965    }
2966
2967    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, HistoryTag wakelockTag,
2968            BitDescription[] descriptions, boolean longNames) {
2969        int diff = oldval ^ newval;
2970        if (diff == 0) return;
2971        boolean didWake = false;
2972        for (int i=0; i<descriptions.length; i++) {
2973            BitDescription bd = descriptions[i];
2974            if ((diff&bd.mask) != 0) {
2975                pw.print(longNames ? " " : ",");
2976                if (bd.shift < 0) {
2977                    pw.print((newval&bd.mask) != 0 ? "+" : "-");
2978                    pw.print(longNames ? bd.name : bd.shortName);
2979                    if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
2980                        didWake = true;
2981                        pw.print("=");
2982                        if (longNames) {
2983                            UserHandle.formatUid(pw, wakelockTag.uid);
2984                            pw.print(":\"");
2985                            pw.print(wakelockTag.string);
2986                            pw.print("\"");
2987                        } else {
2988                            pw.print(wakelockTag.poolIdx);
2989                        }
2990                    }
2991                } else {
2992                    pw.print(longNames ? bd.name : bd.shortName);
2993                    pw.print("=");
2994                    int val = (newval&bd.mask)>>bd.shift;
2995                    if (bd.values != null && val >= 0 && val < bd.values.length) {
2996                        pw.print(longNames? bd.values[val] : bd.shortValues[val]);
2997                    } else {
2998                        pw.print(val);
2999                    }
3000                }
3001            }
3002        }
3003        if (!didWake && wakelockTag != null) {
3004            pw.print(longNames ? " wake_lock=" : ",w=");
3005            if (longNames) {
3006                UserHandle.formatUid(pw, wakelockTag.uid);
3007                pw.print(":\"");
3008                pw.print(wakelockTag.string);
3009                pw.print("\"");
3010            } else {
3011                pw.print(wakelockTag.poolIdx);
3012            }
3013        }
3014    }
3015
3016    public void prepareForDumpLocked() {
3017    }
3018
3019    public static class HistoryPrinter {
3020        int oldState = 0;
3021        int oldState2 = 0;
3022        int oldLevel = -1;
3023        int oldStatus = -1;
3024        int oldHealth = -1;
3025        int oldPlug = -1;
3026        int oldTemp = -1;
3027        int oldVolt = -1;
3028        long lastTime = -1;
3029        long firstTime = -1;
3030
3031        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
3032                boolean verbose) {
3033            if (!checkin) {
3034                pw.print("  ");
3035                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
3036                pw.print(" (");
3037                pw.print(rec.numReadInts);
3038                pw.print(") ");
3039            } else {
3040                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
3041                pw.print(HISTORY_DATA); pw.print(',');
3042                if (lastTime < 0) {
3043                    pw.print(rec.time - baseTime);
3044                } else {
3045                    pw.print(rec.time - lastTime);
3046                }
3047                lastTime = rec.time;
3048            }
3049            if (rec.cmd == HistoryItem.CMD_START) {
3050                if (checkin) {
3051                    pw.print(":");
3052                }
3053                pw.println("START");
3054            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
3055                    || rec.cmd == HistoryItem.CMD_RESET) {
3056                if (checkin) {
3057                    pw.print(":");
3058                }
3059                if (rec.cmd == HistoryItem.CMD_RESET) {
3060                    pw.print("RESET:");
3061                }
3062                pw.print("TIME:");
3063                if (checkin) {
3064                    pw.println(rec.currentTime);
3065                } else {
3066                    pw.print(" ");
3067                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
3068                            rec.currentTime).toString());
3069                }
3070            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
3071                if (checkin) {
3072                    pw.print(":");
3073                }
3074                pw.println("*OVERFLOW*");
3075            } else {
3076                if (!checkin) {
3077                    if (rec.batteryLevel < 10) pw.print("00");
3078                    else if (rec.batteryLevel < 100) pw.print("0");
3079                    pw.print(rec.batteryLevel);
3080                    if (verbose) {
3081                        pw.print(" ");
3082                        if (rec.states < 0) ;
3083                        else if (rec.states < 0x10) pw.print("0000000");
3084                        else if (rec.states < 0x100) pw.print("000000");
3085                        else if (rec.states < 0x1000) pw.print("00000");
3086                        else if (rec.states < 0x10000) pw.print("0000");
3087                        else if (rec.states < 0x100000) pw.print("000");
3088                        else if (rec.states < 0x1000000) pw.print("00");
3089                        else if (rec.states < 0x10000000) pw.print("0");
3090                        pw.print(Integer.toHexString(rec.states));
3091                    }
3092                } else {
3093                    if (oldLevel != rec.batteryLevel) {
3094                        oldLevel = rec.batteryLevel;
3095                        pw.print(",Bl="); pw.print(rec.batteryLevel);
3096                    }
3097                }
3098                if (oldStatus != rec.batteryStatus) {
3099                    oldStatus = rec.batteryStatus;
3100                    pw.print(checkin ? ",Bs=" : " status=");
3101                    switch (oldStatus) {
3102                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
3103                            pw.print(checkin ? "?" : "unknown");
3104                            break;
3105                        case BatteryManager.BATTERY_STATUS_CHARGING:
3106                            pw.print(checkin ? "c" : "charging");
3107                            break;
3108                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
3109                            pw.print(checkin ? "d" : "discharging");
3110                            break;
3111                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
3112                            pw.print(checkin ? "n" : "not-charging");
3113                            break;
3114                        case BatteryManager.BATTERY_STATUS_FULL:
3115                            pw.print(checkin ? "f" : "full");
3116                            break;
3117                        default:
3118                            pw.print(oldStatus);
3119                            break;
3120                    }
3121                }
3122                if (oldHealth != rec.batteryHealth) {
3123                    oldHealth = rec.batteryHealth;
3124                    pw.print(checkin ? ",Bh=" : " health=");
3125                    switch (oldHealth) {
3126                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
3127                            pw.print(checkin ? "?" : "unknown");
3128                            break;
3129                        case BatteryManager.BATTERY_HEALTH_GOOD:
3130                            pw.print(checkin ? "g" : "good");
3131                            break;
3132                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
3133                            pw.print(checkin ? "h" : "overheat");
3134                            break;
3135                        case BatteryManager.BATTERY_HEALTH_DEAD:
3136                            pw.print(checkin ? "d" : "dead");
3137                            break;
3138                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
3139                            pw.print(checkin ? "v" : "over-voltage");
3140                            break;
3141                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
3142                            pw.print(checkin ? "f" : "failure");
3143                            break;
3144                        case BatteryManager.BATTERY_HEALTH_COLD:
3145                            pw.print(checkin ? "c" : "cold");
3146                            break;
3147                        default:
3148                            pw.print(oldHealth);
3149                            break;
3150                    }
3151                }
3152                if (oldPlug != rec.batteryPlugType) {
3153                    oldPlug = rec.batteryPlugType;
3154                    pw.print(checkin ? ",Bp=" : " plug=");
3155                    switch (oldPlug) {
3156                        case 0:
3157                            pw.print(checkin ? "n" : "none");
3158                            break;
3159                        case BatteryManager.BATTERY_PLUGGED_AC:
3160                            pw.print(checkin ? "a" : "ac");
3161                            break;
3162                        case BatteryManager.BATTERY_PLUGGED_USB:
3163                            pw.print(checkin ? "u" : "usb");
3164                            break;
3165                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
3166                            pw.print(checkin ? "w" : "wireless");
3167                            break;
3168                        default:
3169                            pw.print(oldPlug);
3170                            break;
3171                    }
3172                }
3173                if (oldTemp != rec.batteryTemperature) {
3174                    oldTemp = rec.batteryTemperature;
3175                    pw.print(checkin ? ",Bt=" : " temp=");
3176                    pw.print(oldTemp);
3177                }
3178                if (oldVolt != rec.batteryVoltage) {
3179                    oldVolt = rec.batteryVoltage;
3180                    pw.print(checkin ? ",Bv=" : " volt=");
3181                    pw.print(oldVolt);
3182                }
3183                printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
3184                        HISTORY_STATE_DESCRIPTIONS, !checkin);
3185                printBitDescriptions(pw, oldState2, rec.states2, null,
3186                        HISTORY_STATE2_DESCRIPTIONS, !checkin);
3187                if (rec.wakeReasonTag != null) {
3188                    if (checkin) {
3189                        pw.print(",wr=");
3190                        pw.print(rec.wakeReasonTag.poolIdx);
3191                    } else {
3192                        pw.print(" wake_reason=");
3193                        pw.print(rec.wakeReasonTag.uid);
3194                        pw.print(":\"");
3195                        pw.print(rec.wakeReasonTag.string);
3196                        pw.print("\"");
3197                    }
3198                }
3199                if (rec.eventCode != HistoryItem.EVENT_NONE) {
3200                    pw.print(checkin ? "," : " ");
3201                    if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
3202                        pw.print("+");
3203                    } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
3204                        pw.print("-");
3205                    }
3206                    String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
3207                            : HISTORY_EVENT_NAMES;
3208                    int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
3209                            | HistoryItem.EVENT_FLAG_FINISH);
3210                    if (idx >= 0 && idx < eventNames.length) {
3211                        pw.print(eventNames[idx]);
3212                    } else {
3213                        pw.print(checkin ? "Ev" : "event");
3214                        pw.print(idx);
3215                    }
3216                    pw.print("=");
3217                    if (checkin) {
3218                        pw.print(rec.eventTag.poolIdx);
3219                    } else {
3220                        UserHandle.formatUid(pw, rec.eventTag.uid);
3221                        pw.print(":\"");
3222                        pw.print(rec.eventTag.string);
3223                        pw.print("\"");
3224                    }
3225                }
3226                pw.println();
3227                oldState = rec.states;
3228                oldState2 = rec.states2;
3229            }
3230        }
3231    }
3232
3233    private void printSizeValue(PrintWriter pw, long size) {
3234        float result = size;
3235        String suffix = "";
3236        if (result >= 10*1024) {
3237            suffix = "KB";
3238            result = result / 1024;
3239        }
3240        if (result >= 10*1024) {
3241            suffix = "MB";
3242            result = result / 1024;
3243        }
3244        if (result >= 10*1024) {
3245            suffix = "GB";
3246            result = result / 1024;
3247        }
3248        if (result >= 10*1024) {
3249            suffix = "TB";
3250            result = result / 1024;
3251        }
3252        if (result >= 10*1024) {
3253            suffix = "PB";
3254            result = result / 1024;
3255        }
3256        pw.print((int)result);
3257        pw.print(suffix);
3258    }
3259
3260    private static boolean dumpDurationSteps(PrintWriter pw, String header, long[] steps,
3261            int count, boolean checkin) {
3262        if (count <= 0) {
3263            return false;
3264        }
3265        if (!checkin) {
3266            pw.println(header);
3267        }
3268        String[] lineArgs = new String[1];
3269        for (int i=0; i<count; i++) {
3270            if (checkin) {
3271                lineArgs[0] = Long.toString(steps[i]);
3272                dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
3273            } else {
3274                pw.print("  #"); pw.print(i); pw.print(": ");
3275                TimeUtils.formatDuration(steps[i], pw);
3276                pw.println();
3277            }
3278        }
3279        return true;
3280    }
3281
3282    public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
3283    public static final int DUMP_CHARGED_ONLY = 1<<1;
3284    public static final int DUMP_HISTORY_ONLY = 1<<2;
3285    public static final int DUMP_INCLUDE_HISTORY = 1<<3;
3286    public static final int DUMP_VERBOSE = 1<<4;
3287
3288    private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
3289        final HistoryPrinter hprinter = new HistoryPrinter();
3290        final HistoryItem rec = new HistoryItem();
3291        long lastTime = -1;
3292        long baseTime = -1;
3293        boolean printed = false;
3294        HistoryEventTracker tracker = null;
3295        while (getNextHistoryLocked(rec)) {
3296            lastTime = rec.time;
3297            if (baseTime < 0) {
3298                baseTime = lastTime;
3299            }
3300            if (rec.time >= histStart) {
3301                if (histStart >= 0 && !printed) {
3302                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
3303                            || rec.cmd == HistoryItem.CMD_RESET) {
3304                        printed = true;
3305                        hprinter.printNextItem(pw, rec, baseTime, checkin,
3306                                (flags&DUMP_VERBOSE) != 0);
3307                        rec.cmd = HistoryItem.CMD_UPDATE;
3308                    } else if (rec.currentTime != 0) {
3309                        printed = true;
3310                        byte cmd = rec.cmd;
3311                        rec.cmd = HistoryItem.CMD_CURRENT_TIME;
3312                        hprinter.printNextItem(pw, rec, baseTime, checkin,
3313                                (flags&DUMP_VERBOSE) != 0);
3314                        rec.cmd = cmd;
3315                    }
3316                    if (tracker != null) {
3317                        if (rec.cmd != HistoryItem.CMD_UPDATE) {
3318                            hprinter.printNextItem(pw, rec, baseTime, checkin,
3319                                    (flags&DUMP_VERBOSE) != 0);
3320                            rec.cmd = HistoryItem.CMD_UPDATE;
3321                        }
3322                        int oldEventCode = rec.eventCode;
3323                        HistoryTag oldEventTag = rec.eventTag;
3324                        rec.eventTag = new HistoryTag();
3325                        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
3326                            HashMap<String, SparseIntArray> active
3327                                    = tracker.getStateForEvent(i);
3328                            if (active == null) {
3329                                continue;
3330                            }
3331                            for (HashMap.Entry<String, SparseIntArray> ent
3332                                    : active.entrySet()) {
3333                                SparseIntArray uids = ent.getValue();
3334                                for (int j=0; j<uids.size(); j++) {
3335                                    rec.eventCode = i;
3336                                    rec.eventTag.string = ent.getKey();
3337                                    rec.eventTag.uid = uids.keyAt(j);
3338                                    rec.eventTag.poolIdx = uids.valueAt(j);
3339                                    hprinter.printNextItem(pw, rec, baseTime, checkin,
3340                                            (flags&DUMP_VERBOSE) != 0);
3341                                    rec.wakeReasonTag = null;
3342                                    rec.wakelockTag = null;
3343                                }
3344                            }
3345                        }
3346                        rec.eventCode = oldEventCode;
3347                        rec.eventTag = oldEventTag;
3348                        tracker = null;
3349                    }
3350                }
3351                hprinter.printNextItem(pw, rec, baseTime, checkin,
3352                        (flags&DUMP_VERBOSE) != 0);
3353            } else if (rec.eventCode != HistoryItem.EVENT_NONE) {
3354                if (tracker == null) {
3355                    tracker = new HistoryEventTracker();
3356                }
3357                tracker.updateState(rec.eventCode, rec.eventTag.string,
3358                        rec.eventTag.uid, rec.eventTag.poolIdx);
3359            }
3360        }
3361        if (histStart >= 0) {
3362            pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
3363        }
3364    }
3365
3366    /**
3367     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
3368     *
3369     * @param pw a Printer to receive the dump output.
3370     */
3371    @SuppressWarnings("unused")
3372    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
3373        prepareForDumpLocked();
3374
3375        final boolean filtering =
3376                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
3377
3378        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
3379            final long historyTotalSize = getHistoryTotalSize();
3380            final long historyUsedSize = getHistoryUsedSize();
3381            if (startIteratingHistoryLocked()) {
3382                try {
3383                    pw.print("Battery History (");
3384                    pw.print((100*historyUsedSize)/historyTotalSize);
3385                    pw.print("% used, ");
3386                    printSizeValue(pw, historyUsedSize);
3387                    pw.print(" used of ");
3388                    printSizeValue(pw, historyTotalSize);
3389                    pw.print(", ");
3390                    pw.print(getHistoryStringPoolSize());
3391                    pw.print(" strings using ");
3392                    printSizeValue(pw, getHistoryStringPoolBytes());
3393                    pw.println("):");
3394                    dumpHistoryLocked(pw, flags, histStart, false);
3395                    pw.println();
3396                } finally {
3397                    finishIteratingHistoryLocked();
3398                }
3399            }
3400
3401            if (startIteratingOldHistoryLocked()) {
3402                try {
3403                    final HistoryItem rec = new HistoryItem();
3404                    pw.println("Old battery History:");
3405                    HistoryPrinter hprinter = new HistoryPrinter();
3406                    long baseTime = -1;
3407                    while (getNextOldHistoryLocked(rec)) {
3408                        if (baseTime < 0) {
3409                            baseTime = rec.time;
3410                        }
3411                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
3412                    }
3413                    pw.println();
3414                } finally {
3415                    finishIteratingOldHistoryLocked();
3416                }
3417            }
3418        }
3419
3420        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
3421            return;
3422        }
3423
3424        if (!filtering) {
3425            SparseArray<? extends Uid> uidStats = getUidStats();
3426            final int NU = uidStats.size();
3427            boolean didPid = false;
3428            long nowRealtime = SystemClock.elapsedRealtime();
3429            for (int i=0; i<NU; i++) {
3430                Uid uid = uidStats.valueAt(i);
3431                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
3432                if (pids != null) {
3433                    for (int j=0; j<pids.size(); j++) {
3434                        Uid.Pid pid = pids.valueAt(j);
3435                        if (!didPid) {
3436                            pw.println("Per-PID Stats:");
3437                            didPid = true;
3438                        }
3439                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
3440                                ? (nowRealtime - pid.mWakeStartMs) : 0);
3441                        pw.print("  PID "); pw.print(pids.keyAt(j));
3442                                pw.print(" wake time: ");
3443                                TimeUtils.formatDuration(time, pw);
3444                                pw.println("");
3445                    }
3446                }
3447            }
3448            if (didPid) {
3449                pw.println();
3450            }
3451            if (dumpDurationSteps(pw, "Discharge step durations:", getDischargeStepDurationsArray(),
3452                    getNumDischargeStepDurations(), false)) {
3453                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
3454                if (timeRemaining >= 0) {
3455                    pw.print("  Estimated discharge time remaining: ");
3456                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
3457                    pw.println();
3458                }
3459                pw.println();
3460            }
3461            if (dumpDurationSteps(pw, "Charge step durations:", getChargeStepDurationsArray(),
3462                    getNumChargeStepDurations(), false)) {
3463                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
3464                if (timeRemaining >= 0) {
3465                    pw.print("  Estimated charge time remaining: ");
3466                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
3467                    pw.println();
3468                }
3469                pw.println();
3470            }
3471        }
3472
3473        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
3474            pw.println("Statistics since last charge:");
3475            pw.println("  System starts: " + getStartCount()
3476                    + ", currently on battery: " + getIsOnBattery());
3477            dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
3478            pw.println();
3479        }
3480        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
3481            pw.println("Statistics since last unplugged:");
3482            dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
3483        }
3484    }
3485
3486    @SuppressWarnings("unused")
3487    public void dumpCheckinLocked(Context context, PrintWriter pw,
3488            List<ApplicationInfo> apps, int flags, long histStart) {
3489        prepareForDumpLocked();
3490
3491        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
3492
3493        final boolean filtering =
3494                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
3495
3496        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
3497            if (startIteratingHistoryLocked()) {
3498                try {
3499                    for (int i=0; i<getHistoryStringPoolSize(); i++) {
3500                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
3501                        pw.print(HISTORY_STRING_POOL); pw.print(',');
3502                        pw.print(i);
3503                        pw.print(",");
3504                        pw.print(getHistoryTagPoolUid(i));
3505                        pw.print(",\"");
3506                        String str = getHistoryTagPoolString(i);
3507                        str = str.replace("\\", "\\\\");
3508                        str = str.replace("\"", "\\\"");
3509                        pw.print(str);
3510                        pw.print("\"");
3511                        pw.println();
3512                    }
3513                    dumpHistoryLocked(pw, flags, histStart, true);
3514                } finally {
3515                    finishIteratingHistoryLocked();
3516                }
3517            }
3518        }
3519
3520        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
3521            return;
3522        }
3523
3524        if (apps != null) {
3525            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
3526            for (int i=0; i<apps.size(); i++) {
3527                ApplicationInfo ai = apps.get(i);
3528                ArrayList<String> pkgs = uids.get(ai.uid);
3529                if (pkgs == null) {
3530                    pkgs = new ArrayList<String>();
3531                    uids.put(ai.uid, pkgs);
3532                }
3533                pkgs.add(ai.packageName);
3534            }
3535            SparseArray<? extends Uid> uidStats = getUidStats();
3536            final int NU = uidStats.size();
3537            String[] lineArgs = new String[2];
3538            for (int i=0; i<NU; i++) {
3539                int uid = uidStats.keyAt(i);
3540                ArrayList<String> pkgs = uids.get(uid);
3541                if (pkgs != null) {
3542                    for (int j=0; j<pkgs.size(); j++) {
3543                        lineArgs[0] = Integer.toString(uid);
3544                        lineArgs[1] = pkgs.get(j);
3545                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
3546                                (Object[])lineArgs);
3547                    }
3548                }
3549            }
3550        }
3551        if (!filtering) {
3552            dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
3553                    getNumDischargeStepDurations(), true);
3554            String[] lineArgs = new String[1];
3555            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
3556            if (timeRemaining >= 0) {
3557                lineArgs[0] = Long.toString(timeRemaining);
3558                dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
3559                        (Object[])lineArgs);
3560            }
3561            dumpDurationSteps(pw, CHARGE_STEP_DATA, getChargeStepDurationsArray(),
3562                    getNumChargeStepDurations(), true);
3563            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
3564            if (timeRemaining >= 0) {
3565                lineArgs[0] = Long.toString(timeRemaining);
3566                dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
3567                        (Object[])lineArgs);
3568            }
3569        }
3570        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
3571            dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
3572        }
3573        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
3574            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
3575        }
3576    }
3577}
3578