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