BatteryStats.java revision ec43a6bc17d90058ba2c00e016846c863ab239bc
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.List;
25import java.util.Map;
26
27import android.content.pm.ApplicationInfo;
28import android.telephony.SignalStrength;
29import android.util.Log;
30import android.util.Printer;
31import android.util.Slog;
32import android.util.SparseArray;
33import android.util.TimeUtils;
34
35/**
36 * A class providing access to battery usage statistics, including information on
37 * wakelocks, processes, packages, and services.  All times are represented in microseconds
38 * except where indicated otherwise.
39 * @hide
40 */
41public abstract class BatteryStats implements Parcelable {
42
43    private static final boolean LOCAL_LOGV = false;
44
45    /**
46     * A constant indicating a partial wake lock timer.
47     */
48    public static final int WAKE_TYPE_PARTIAL = 0;
49
50    /**
51     * A constant indicating a full wake lock timer.
52     */
53    public static final int WAKE_TYPE_FULL = 1;
54
55    /**
56     * A constant indicating a window wake lock timer.
57     */
58    public static final int WAKE_TYPE_WINDOW = 2;
59
60    /**
61     * A constant indicating a sensor timer.
62     */
63    public static final int SENSOR = 3;
64
65    /**
66     * A constant indicating a a wifi running timer
67     */
68    public static final int WIFI_RUNNING = 4;
69
70    /**
71     * A constant indicating a full wifi lock timer
72     */
73    public static final int FULL_WIFI_LOCK = 5;
74
75    /**
76     * A constant indicating a wifi scan
77     */
78    public static final int WIFI_SCAN = 6;
79
80     /**
81      * A constant indicating a wifi multicast timer
82      */
83     public static final int WIFI_MULTICAST_ENABLED = 7;
84
85    /**
86     * A constant indicating an audio turn on timer
87     */
88    public static final int AUDIO_TURNED_ON = 7;
89
90    /**
91     * A constant indicating a video turn on timer
92     */
93    public static final int VIDEO_TURNED_ON = 8;
94
95    /**
96     * A constant indicating a vibrator on timer
97     */
98    public static final int VIBRATOR_ON = 9;
99
100    /**
101     * A constant indicating a foreground activity timer
102     */
103    public static final int FOREGROUND_ACTIVITY = 10;
104
105    /**
106     * Include all of the data in the stats, including previously saved data.
107     */
108    public static final int STATS_SINCE_CHARGED = 0;
109
110    /**
111     * Include only the last run in the stats.
112     */
113    public static final int STATS_LAST = 1;
114
115    /**
116     * Include only the current run in the stats.
117     */
118    public static final int STATS_CURRENT = 2;
119
120    /**
121     * Include only the run since the last time the device was unplugged in the stats.
122     */
123    public static final int STATS_SINCE_UNPLUGGED = 3;
124
125    // NOTE: Update this list if you add/change any stats above.
126    // These characters are supposed to represent "total", "last", "current",
127    // and "unplugged". They were shortened for efficiency sake.
128    private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
129
130    /**
131     * Bump the version on this if the checkin format changes.
132     */
133    private static final int BATTERY_STATS_CHECKIN_VERSION = 6;
134
135    private static final long BYTES_PER_KB = 1024;
136    private static final long BYTES_PER_MB = 1048576; // 1024^2
137    private static final long BYTES_PER_GB = 1073741824; //1024^3
138
139
140    private static final String UID_DATA = "uid";
141    private static final String APK_DATA = "apk";
142    private static final String PROCESS_DATA = "pr";
143    private static final String SENSOR_DATA = "sr";
144    private static final String VIBRATOR_DATA = "vib";
145    private static final String FOREGROUND_DATA = "fg";
146    private static final String WAKELOCK_DATA = "wl";
147    private static final String KERNEL_WAKELOCK_DATA = "kwl";
148    private static final String NETWORK_DATA = "nt";
149    private static final String USER_ACTIVITY_DATA = "ua";
150    private static final String BATTERY_DATA = "bt";
151    private static final String BATTERY_DISCHARGE_DATA = "dc";
152    private static final String BATTERY_LEVEL_DATA = "lv";
153    private static final String WIFI_DATA = "wfl";
154    private static final String MISC_DATA = "m";
155    private static final String SCREEN_BRIGHTNESS_DATA = "br";
156    private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
157    private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
158    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
159    private static final String DATA_CONNECTION_TIME_DATA = "dct";
160    private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
161
162    private final StringBuilder mFormatBuilder = new StringBuilder(32);
163    private final Formatter mFormatter = new Formatter(mFormatBuilder);
164
165    /**
166     * State for keeping track of counting information.
167     */
168    public static abstract class Counter {
169
170        /**
171         * Returns the count associated with this Counter for the
172         * selected type of statistics.
173         *
174         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
175         */
176        public abstract int getCountLocked(int which);
177
178        /**
179         * Temporary for debugging.
180         */
181        public abstract void logState(Printer pw, String prefix);
182    }
183
184    /**
185     * State for keeping track of timing information.
186     */
187    public static abstract class Timer {
188
189        /**
190         * Returns the count associated with this Timer for the
191         * selected type of statistics.
192         *
193         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
194         */
195        public abstract int getCountLocked(int which);
196
197        /**
198         * Returns the total time in microseconds associated with this Timer for the
199         * selected type of statistics.
200         *
201         * @param batteryRealtime system realtime on  battery in microseconds
202         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
203         * @return a time in microseconds
204         */
205        public abstract long getTotalTimeLocked(long batteryRealtime, int which);
206
207        /**
208         * Temporary for debugging.
209         */
210        public abstract void logState(Printer pw, String prefix);
211    }
212
213    /**
214     * The statistics associated with a particular uid.
215     */
216    public static abstract class Uid {
217
218        /**
219         * Returns a mapping containing wakelock statistics.
220         *
221         * @return a Map from Strings to Uid.Wakelock objects.
222         */
223        public abstract Map<String, ? extends Wakelock> getWakelockStats();
224
225        /**
226         * The statistics associated with a particular wake lock.
227         */
228        public static abstract class Wakelock {
229            public abstract Timer getWakeTime(int type);
230        }
231
232        /**
233         * Returns a mapping containing sensor statistics.
234         *
235         * @return a Map from Integer sensor ids to Uid.Sensor objects.
236         */
237        public abstract Map<Integer, ? extends Sensor> getSensorStats();
238
239        /**
240         * Returns a mapping containing active process data.
241         */
242        public abstract SparseArray<? extends Pid> getPidStats();
243
244        /**
245         * Returns a mapping containing process statistics.
246         *
247         * @return a Map from Strings to Uid.Proc objects.
248         */
249        public abstract Map<String, ? extends Proc> getProcessStats();
250
251        /**
252         * Returns a mapping containing package statistics.
253         *
254         * @return a Map from Strings to Uid.Pkg objects.
255         */
256        public abstract Map<String, ? extends Pkg> getPackageStats();
257
258        /**
259         * {@hide}
260         */
261        public abstract int getUid();
262
263        /**
264         * {@hide}
265         */
266        public abstract long getTcpBytesReceived(int which);
267
268        /**
269         * {@hide}
270         */
271        public abstract long getTcpBytesSent(int which);
272
273        public abstract void noteWifiRunningLocked();
274        public abstract void noteWifiStoppedLocked();
275        public abstract void noteFullWifiLockAcquiredLocked();
276        public abstract void noteFullWifiLockReleasedLocked();
277        public abstract void noteWifiScanStartedLocked();
278        public abstract void noteWifiScanStoppedLocked();
279        public abstract void noteWifiMulticastEnabledLocked();
280        public abstract void noteWifiMulticastDisabledLocked();
281        public abstract void noteAudioTurnedOnLocked();
282        public abstract void noteAudioTurnedOffLocked();
283        public abstract void noteVideoTurnedOnLocked();
284        public abstract void noteVideoTurnedOffLocked();
285        public abstract void noteActivityResumedLocked();
286        public abstract void noteActivityPausedLocked();
287        public abstract long getWifiRunningTime(long batteryRealtime, int which);
288        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
289        public abstract long getWifiScanTime(long batteryRealtime, int which);
290        public abstract long getWifiMulticastTime(long batteryRealtime,
291                                                  int which);
292        public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
293        public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
294        public abstract Timer getForegroundActivityTimer();
295        public abstract Timer getVibratorOnTimer();
296
297        /**
298         * Note that these must match the constants in android.os.PowerManager.
299         * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
300         * also be bumped.
301         */
302        static final String[] USER_ACTIVITY_TYPES = {
303            "other", "button", "touch"
304        };
305
306        public static final int NUM_USER_ACTIVITY_TYPES = 3;
307
308        public abstract void noteUserActivityLocked(int type);
309        public abstract boolean hasUserActivity();
310        public abstract int getUserActivityCount(int type, int which);
311
312        public static abstract class Sensor {
313            /*
314             * FIXME: it's not correct to use this magic value because it
315             * could clash with a sensor handle (which are defined by
316             * the sensor HAL, and therefore out of our control
317             */
318            // Magic sensor number for the GPS.
319            public static final int GPS = -10000;
320
321            public abstract int getHandle();
322
323            public abstract Timer getSensorTime();
324        }
325
326        public class Pid {
327            public long mWakeSum;
328            public long mWakeStart;
329        }
330
331        /**
332         * The statistics associated with a particular process.
333         */
334        public static abstract class Proc {
335
336            public static class ExcessivePower {
337                public static final int TYPE_WAKE = 1;
338                public static final int TYPE_CPU = 2;
339
340                public int type;
341                public long overTime;
342                public long usedTime;
343            }
344
345            /**
346             * Returns the total time (in 1/100 sec) spent executing in user code.
347             *
348             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
349             */
350            public abstract long getUserTime(int which);
351
352            /**
353             * Returns the total time (in 1/100 sec) spent executing in system code.
354             *
355             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
356             */
357            public abstract long getSystemTime(int which);
358
359            /**
360             * Returns the number of times the process has been started.
361             *
362             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
363             */
364            public abstract int getStarts(int which);
365
366            /**
367             * Returns the cpu time spent in microseconds while the process was in the foreground.
368             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
369             * @return foreground cpu time in microseconds
370             */
371            public abstract long getForegroundTime(int which);
372
373            /**
374             * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
375             * @param speedStep the index of the CPU speed. This is not the actual speed of the
376             * CPU.
377             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
378             * @see BatteryStats#getCpuSpeedSteps()
379             */
380            public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
381
382            public abstract int countExcessivePowers();
383
384            public abstract ExcessivePower getExcessivePower(int i);
385        }
386
387        /**
388         * The statistics associated with a particular package.
389         */
390        public static abstract class Pkg {
391
392            /**
393             * Returns the number of times this package has done something that could wake up the
394             * device from sleep.
395             *
396             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
397             */
398            public abstract int getWakeups(int which);
399
400            /**
401             * Returns a mapping containing service statistics.
402             */
403            public abstract Map<String, ? extends Serv> getServiceStats();
404
405            /**
406             * The statistics associated with a particular service.
407             */
408            public abstract class Serv {
409
410                /**
411                 * Returns the amount of time spent started.
412                 *
413                 * @param batteryUptime elapsed uptime on battery in microseconds.
414                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
415                 * @return
416                 */
417                public abstract long getStartTime(long batteryUptime, int which);
418
419                /**
420                 * Returns the total number of times startService() has been called.
421                 *
422                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
423                 */
424                public abstract int getStarts(int which);
425
426                /**
427                 * Returns the total number times the service has been launched.
428                 *
429                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
430                 */
431                public abstract int getLaunches(int which);
432            }
433        }
434    }
435
436    public final static class HistoryItem implements Parcelable {
437        static final String TAG = "HistoryItem";
438        static final boolean DEBUG = false;
439
440        public HistoryItem next;
441
442        public long time;
443
444        public static final byte CMD_NULL = 0;
445        public static final byte CMD_UPDATE = 1;
446        public static final byte CMD_START = 2;
447        public static final byte CMD_OVERFLOW = 3;
448
449        public byte cmd = CMD_NULL;
450
451        public byte batteryLevel;
452        public byte batteryStatus;
453        public byte batteryHealth;
454        public byte batteryPlugType;
455
456        public char batteryTemperature;
457        public char batteryVoltage;
458
459        // Constants from SCREEN_BRIGHTNESS_*
460        public static final int STATE_BRIGHTNESS_MASK = 0x0000000f;
461        public static final int STATE_BRIGHTNESS_SHIFT = 0;
462        // Constants from SIGNAL_STRENGTH_*
463        public static final int STATE_SIGNAL_STRENGTH_MASK = 0x000000f0;
464        public static final int STATE_SIGNAL_STRENGTH_SHIFT = 4;
465        // Constants from ServiceState.STATE_*
466        public static final int STATE_PHONE_STATE_MASK = 0x00000f00;
467        public static final int STATE_PHONE_STATE_SHIFT = 8;
468        // Constants from DATA_CONNECTION_*
469        public static final int STATE_DATA_CONNECTION_MASK = 0x0000f000;
470        public static final int STATE_DATA_CONNECTION_SHIFT = 12;
471
472        // These states always appear directly in the first int token
473        // of a delta change; they should be ones that change relatively
474        // frequently.
475        public static final int STATE_WAKE_LOCK_FLAG = 1<<30;
476        public static final int STATE_SENSOR_ON_FLAG = 1<<29;
477        public static final int STATE_GPS_ON_FLAG = 1<<28;
478        public static final int STATE_PHONE_SCANNING_FLAG = 1<<27;
479        public static final int STATE_WIFI_RUNNING_FLAG = 1<<26;
480        public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<25;
481        public static final int STATE_WIFI_SCAN_FLAG = 1<<24;
482        public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<23;
483        // These are on the lower bits used for the command; if they change
484        // we need to write another int of data.
485        public static final int STATE_AUDIO_ON_FLAG = 1<<22;
486        public static final int STATE_VIDEO_ON_FLAG = 1<<21;
487        public static final int STATE_SCREEN_ON_FLAG = 1<<20;
488        public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<19;
489        public static final int STATE_PHONE_IN_CALL_FLAG = 1<<18;
490        public static final int STATE_WIFI_ON_FLAG = 1<<17;
491        public static final int STATE_BLUETOOTH_ON_FLAG = 1<<16;
492
493        public static final int MOST_INTERESTING_STATES =
494            STATE_BATTERY_PLUGGED_FLAG | STATE_SCREEN_ON_FLAG
495            | STATE_GPS_ON_FLAG | STATE_PHONE_IN_CALL_FLAG;
496
497        public int states;
498
499        public HistoryItem() {
500        }
501
502        public HistoryItem(long time, Parcel src) {
503            this.time = time;
504            readFromParcel(src);
505        }
506
507        public int describeContents() {
508            return 0;
509        }
510
511        public void writeToParcel(Parcel dest, int flags) {
512            dest.writeLong(time);
513            int bat = (((int)cmd)&0xff)
514                    | ((((int)batteryLevel)<<8)&0xff00)
515                    | ((((int)batteryStatus)<<16)&0xf0000)
516                    | ((((int)batteryHealth)<<20)&0xf00000)
517                    | ((((int)batteryPlugType)<<24)&0xf000000);
518            dest.writeInt(bat);
519            bat = (((int)batteryTemperature)&0xffff)
520                    | ((((int)batteryVoltage)<<16)&0xffff0000);
521            dest.writeInt(bat);
522            dest.writeInt(states);
523        }
524
525        private void readFromParcel(Parcel src) {
526            int bat = src.readInt();
527            cmd = (byte)(bat&0xff);
528            batteryLevel = (byte)((bat>>8)&0xff);
529            batteryStatus = (byte)((bat>>16)&0xf);
530            batteryHealth = (byte)((bat>>20)&0xf);
531            batteryPlugType = (byte)((bat>>24)&0xf);
532            bat = src.readInt();
533            batteryTemperature = (char)(bat&0xffff);
534            batteryVoltage = (char)((bat>>16)&0xffff);
535            states = src.readInt();
536        }
537
538        // Part of initial delta int that specifies the time delta.
539        static final int DELTA_TIME_MASK = 0x3ffff;
540        static final int DELTA_TIME_ABS = 0x3fffd;    // Following is an entire abs update.
541        static final int DELTA_TIME_INT = 0x3fffe;    // The delta is a following int
542        static final int DELTA_TIME_LONG = 0x3ffff;   // The delta is a following long
543        // Part of initial delta int holding the command code.
544        static final int DELTA_CMD_MASK = 0x3;
545        static final int DELTA_CMD_SHIFT = 18;
546        // Flag in delta int: a new battery level int follows.
547        static final int DELTA_BATTERY_LEVEL_FLAG = 1<<20;
548        // Flag in delta int: a new full state and battery status int follows.
549        static final int DELTA_STATE_FLAG = 1<<21;
550        static final int DELTA_STATE_MASK = 0xffc00000;
551
552        public void writeDelta(Parcel dest, HistoryItem last) {
553            if (last == null || last.cmd != CMD_UPDATE) {
554                dest.writeInt(DELTA_TIME_ABS);
555                writeToParcel(dest, 0);
556                return;
557            }
558
559            final long deltaTime = time - last.time;
560            final int lastBatteryLevelInt = last.buildBatteryLevelInt();
561            final int lastStateInt = last.buildStateInt();
562
563            int deltaTimeToken;
564            if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
565                deltaTimeToken = DELTA_TIME_LONG;
566            } else if (deltaTime >= DELTA_TIME_ABS) {
567                deltaTimeToken = DELTA_TIME_INT;
568            } else {
569                deltaTimeToken = (int)deltaTime;
570            }
571            int firstToken = deltaTimeToken
572                    | (cmd<<DELTA_CMD_SHIFT)
573                    | (states&DELTA_STATE_MASK);
574            final int batteryLevelInt = buildBatteryLevelInt();
575            final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
576            if (batteryLevelIntChanged) {
577                firstToken |= DELTA_BATTERY_LEVEL_FLAG;
578            }
579            final int stateInt = buildStateInt();
580            final boolean stateIntChanged = stateInt != lastStateInt;
581            if (stateIntChanged) {
582                firstToken |= DELTA_STATE_FLAG;
583            }
584            dest.writeInt(firstToken);
585            if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
586                    + " deltaTime=" + deltaTime);
587
588            if (deltaTimeToken >= DELTA_TIME_INT) {
589                if (deltaTimeToken == DELTA_TIME_INT) {
590                    if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
591                    dest.writeInt((int)deltaTime);
592                } else {
593                    if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
594                    dest.writeLong(deltaTime);
595                }
596            }
597            if (batteryLevelIntChanged) {
598                dest.writeInt(batteryLevelInt);
599                if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
600                        + Integer.toHexString(batteryLevelInt)
601                        + " batteryLevel=" + batteryLevel
602                        + " batteryTemp=" + (int)batteryTemperature
603                        + " batteryVolt=" + (int)batteryVoltage);
604            }
605            if (stateIntChanged) {
606                dest.writeInt(stateInt);
607                if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
608                        + Integer.toHexString(stateInt)
609                        + " batteryStatus=" + batteryStatus
610                        + " batteryHealth=" + batteryHealth
611                        + " batteryPlugType=" + batteryPlugType
612                        + " states=0x" + Integer.toHexString(states));
613            }
614        }
615
616        private int buildBatteryLevelInt() {
617            return ((((int)batteryLevel)<<24)&0xff000000)
618                    | ((((int)batteryTemperature)<<14)&0x00ffc000)
619                    | (((int)batteryVoltage)&0x00003fff);
620        }
621
622        private int buildStateInt() {
623            return ((((int)batteryStatus)<<28)&0xf0000000)
624                    | ((((int)batteryHealth)<<24)&0x0f000000)
625                    | ((((int)batteryPlugType)<<22)&0x00c00000)
626                    | (states&(~DELTA_STATE_MASK));
627        }
628
629        public void readDelta(Parcel src) {
630            int firstToken = src.readInt();
631            int deltaTimeToken = firstToken&DELTA_TIME_MASK;
632            cmd = (byte)((firstToken>>DELTA_CMD_SHIFT)&DELTA_CMD_MASK);
633            if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
634                    + " deltaTimeToken=" + deltaTimeToken);
635
636            if (deltaTimeToken < DELTA_TIME_ABS) {
637                time += deltaTimeToken;
638            } else if (deltaTimeToken == DELTA_TIME_ABS) {
639                time = src.readLong();
640                readFromParcel(src);
641                return;
642            } else if (deltaTimeToken == DELTA_TIME_INT) {
643                int delta = src.readInt();
644                time += delta;
645                if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + time);
646            } else {
647                long delta = src.readLong();
648                if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + time);
649                time += delta;
650            }
651
652            if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
653                int batteryLevelInt = src.readInt();
654                batteryLevel = (byte)((batteryLevelInt>>24)&0xff);
655                batteryTemperature = (char)((batteryLevelInt>>14)&0x3ff);
656                batteryVoltage = (char)(batteryLevelInt&0x3fff);
657                if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
658                        + Integer.toHexString(batteryLevelInt)
659                        + " batteryLevel=" + batteryLevel
660                        + " batteryTemp=" + (int)batteryTemperature
661                        + " batteryVolt=" + (int)batteryVoltage);
662            }
663
664            if ((firstToken&DELTA_STATE_FLAG) != 0) {
665                int stateInt = src.readInt();
666                states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK));
667                batteryStatus = (byte)((stateInt>>28)&0xf);
668                batteryHealth = (byte)((stateInt>>24)&0xf);
669                batteryPlugType = (byte)((stateInt>>22)&0x3);
670                if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
671                        + Integer.toHexString(stateInt)
672                        + " batteryStatus=" + batteryStatus
673                        + " batteryHealth=" + batteryHealth
674                        + " batteryPlugType=" + batteryPlugType
675                        + " states=0x" + Integer.toHexString(states));
676            } else {
677                states = (firstToken&DELTA_STATE_MASK) | (states&(~DELTA_STATE_MASK));
678            }
679        }
680
681        public void clear() {
682            time = 0;
683            cmd = CMD_NULL;
684            batteryLevel = 0;
685            batteryStatus = 0;
686            batteryHealth = 0;
687            batteryPlugType = 0;
688            batteryTemperature = 0;
689            batteryVoltage = 0;
690            states = 0;
691        }
692
693        public void setTo(HistoryItem o) {
694            time = o.time;
695            cmd = o.cmd;
696            batteryLevel = o.batteryLevel;
697            batteryStatus = o.batteryStatus;
698            batteryHealth = o.batteryHealth;
699            batteryPlugType = o.batteryPlugType;
700            batteryTemperature = o.batteryTemperature;
701            batteryVoltage = o.batteryVoltage;
702            states = o.states;
703        }
704
705        public void setTo(long time, byte cmd, HistoryItem o) {
706            this.time = time;
707            this.cmd = cmd;
708            batteryLevel = o.batteryLevel;
709            batteryStatus = o.batteryStatus;
710            batteryHealth = o.batteryHealth;
711            batteryPlugType = o.batteryPlugType;
712            batteryTemperature = o.batteryTemperature;
713            batteryVoltage = o.batteryVoltage;
714            states = o.states;
715        }
716
717        public boolean same(HistoryItem o) {
718            return batteryLevel == o.batteryLevel
719                    && batteryStatus == o.batteryStatus
720                    && batteryHealth == o.batteryHealth
721                    && batteryPlugType == o.batteryPlugType
722                    && batteryTemperature == o.batteryTemperature
723                    && batteryVoltage == o.batteryVoltage
724                    && states == o.states;
725        }
726    }
727
728    public static final class BitDescription {
729        public final int mask;
730        public final int shift;
731        public final String name;
732        public final String[] values;
733
734        public BitDescription(int mask, String name) {
735            this.mask = mask;
736            this.shift = -1;
737            this.name = name;
738            this.values = null;
739        }
740
741        public BitDescription(int mask, int shift, String name, String[] values) {
742            this.mask = mask;
743            this.shift = shift;
744            this.name = name;
745            this.values = values;
746        }
747    }
748
749    public abstract boolean startIteratingHistoryLocked();
750
751    public abstract boolean getNextHistoryLocked(HistoryItem out);
752
753    public abstract void finishIteratingHistoryLocked();
754
755    public abstract boolean startIteratingOldHistoryLocked();
756
757    public abstract boolean getNextOldHistoryLocked(HistoryItem out);
758
759    public abstract void finishIteratingOldHistoryLocked();
760
761    /**
762     * Return the base time offset for the battery history.
763     */
764    public abstract long getHistoryBaseTime();
765
766    /**
767     * Returns the number of times the device has been started.
768     */
769    public abstract int getStartCount();
770
771    /**
772     * Returns the time in microseconds that the screen has been on while the device was
773     * running on battery.
774     *
775     * {@hide}
776     */
777    public abstract long getScreenOnTime(long batteryRealtime, int which);
778
779    public static final int SCREEN_BRIGHTNESS_DARK = 0;
780    public static final int SCREEN_BRIGHTNESS_DIM = 1;
781    public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
782    public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
783    public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
784
785    static final String[] SCREEN_BRIGHTNESS_NAMES = {
786        "dark", "dim", "medium", "light", "bright"
787    };
788
789    public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
790
791    /**
792     * Returns the time in microseconds that the screen has been on with
793     * the given brightness
794     *
795     * {@hide}
796     */
797    public abstract long getScreenBrightnessTime(int brightnessBin,
798            long batteryRealtime, int which);
799
800    public abstract int getInputEventCount(int which);
801
802    /**
803     * Returns the time in microseconds that the phone has been on while the device was
804     * running on battery.
805     *
806     * {@hide}
807     */
808    public abstract long getPhoneOnTime(long batteryRealtime, int which);
809
810    /**
811     * Returns the time in microseconds that the phone has been running with
812     * the given signal strength.
813     *
814     * {@hide}
815     */
816    public abstract long getPhoneSignalStrengthTime(int strengthBin,
817            long batteryRealtime, int which);
818
819    /**
820     * Returns the time in microseconds that the phone has been trying to
821     * acquire a signal.
822     *
823     * {@hide}
824     */
825    public abstract long getPhoneSignalScanningTime(
826            long batteryRealtime, int which);
827
828    /**
829     * Returns the number of times the phone has entered the given signal strength.
830     *
831     * {@hide}
832     */
833    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
834
835    public static final int DATA_CONNECTION_NONE = 0;
836    public static final int DATA_CONNECTION_GPRS = 1;
837    public static final int DATA_CONNECTION_EDGE = 2;
838    public static final int DATA_CONNECTION_UMTS = 3;
839    public static final int DATA_CONNECTION_CDMA = 4;
840    public static final int DATA_CONNECTION_EVDO_0 = 5;
841    public static final int DATA_CONNECTION_EVDO_A = 6;
842    public static final int DATA_CONNECTION_1xRTT = 7;
843    public static final int DATA_CONNECTION_HSDPA = 8;
844    public static final int DATA_CONNECTION_HSUPA = 9;
845    public static final int DATA_CONNECTION_HSPA = 10;
846    public static final int DATA_CONNECTION_IDEN = 11;
847    public static final int DATA_CONNECTION_EVDO_B = 12;
848    public static final int DATA_CONNECTION_LTE = 13;
849    public static final int DATA_CONNECTION_EHRPD = 14;
850    public static final int DATA_CONNECTION_OTHER = 15;
851
852    static final String[] DATA_CONNECTION_NAMES = {
853        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
854        "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
855        "ehrpd", "other"
856    };
857
858    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
859
860    /**
861     * Returns the time in microseconds that the phone has been running with
862     * the given data connection.
863     *
864     * {@hide}
865     */
866    public abstract long getPhoneDataConnectionTime(int dataType,
867            long batteryRealtime, int which);
868
869    /**
870     * Returns the number of times the phone has entered the given data
871     * connection type.
872     *
873     * {@hide}
874     */
875    public abstract int getPhoneDataConnectionCount(int dataType, int which);
876
877    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS
878            = new BitDescription[] {
879        new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged"),
880        new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen"),
881        new BitDescription(HistoryItem.STATE_GPS_ON_FLAG, "gps"),
882        new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call"),
883        new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning"),
884        new BitDescription(HistoryItem.STATE_WIFI_ON_FLAG, "wifi"),
885        new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running"),
886        new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock"),
887        new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan"),
888        new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast"),
889        new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth"),
890        new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio"),
891        new BitDescription(HistoryItem.STATE_VIDEO_ON_FLAG, "video"),
892        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock"),
893        new BitDescription(HistoryItem.STATE_SENSOR_ON_FLAG, "sensor"),
894        new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
895                HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness",
896                SCREEN_BRIGHTNESS_NAMES),
897        new BitDescription(HistoryItem.STATE_SIGNAL_STRENGTH_MASK,
898                HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT, "signal_strength",
899                SignalStrength.SIGNAL_STRENGTH_NAMES),
900        new BitDescription(HistoryItem.STATE_PHONE_STATE_MASK,
901                HistoryItem.STATE_PHONE_STATE_SHIFT, "phone_state",
902                new String[] {"in", "out", "emergency", "off"}),
903        new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
904                HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn",
905                DATA_CONNECTION_NAMES),
906    };
907
908    /**
909     * Returns the time in microseconds that wifi has been on while the device was
910     * running on battery.
911     *
912     * {@hide}
913     */
914    public abstract long getWifiOnTime(long batteryRealtime, int which);
915
916    /**
917     * Returns the time in microseconds that wifi has been on and the driver has
918     * been in the running state while the device was running on battery.
919     *
920     * {@hide}
921     */
922    public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
923
924    /**
925     * Returns the time in microseconds that bluetooth has been on while the device was
926     * running on battery.
927     *
928     * {@hide}
929     */
930    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
931
932    /**
933     * Return whether we are currently running on battery.
934     */
935    public abstract boolean getIsOnBattery();
936
937    /**
938     * Returns a SparseArray containing the statistics for each uid.
939     */
940    public abstract SparseArray<? extends Uid> getUidStats();
941
942    /**
943     * Returns the current battery uptime in microseconds.
944     *
945     * @param curTime the amount of elapsed realtime in microseconds.
946     */
947    public abstract long getBatteryUptime(long curTime);
948
949    /**
950     * @deprecated use getRadioDataUptime
951     */
952    public long getRadioDataUptimeMs() {
953        return getRadioDataUptime() / 1000;
954    }
955
956    /**
957     * Returns the time that the radio was on for data transfers.
958     * @return the uptime in microseconds while unplugged
959     */
960    public abstract long getRadioDataUptime();
961
962    /**
963     * Returns the current battery realtime in microseconds.
964     *
965     * @param curTime the amount of elapsed realtime in microseconds.
966     */
967    public abstract long getBatteryRealtime(long curTime);
968
969    /**
970     * Returns the battery percentage level at the last time the device was unplugged from power, or
971     * the last time it booted on battery power.
972     */
973    public abstract int getDischargeStartLevel();
974
975    /**
976     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
977     * returns the level at the last plug event.
978     */
979    public abstract int getDischargeCurrentLevel();
980
981    /**
982     * Get the amount the battery has discharged since the stats were
983     * last reset after charging, as a lower-end approximation.
984     */
985    public abstract int getLowDischargeAmountSinceCharge();
986
987    /**
988     * Get the amount the battery has discharged since the stats were
989     * last reset after charging, as an upper-end approximation.
990     */
991    public abstract int getHighDischargeAmountSinceCharge();
992
993    /**
994     * Get the amount the battery has discharged while the screen was on,
995     * since the last time power was unplugged.
996     */
997    public abstract int getDischargeAmountScreenOn();
998
999    /**
1000     * Get the amount the battery has discharged while the screen was on,
1001     * since the last time the device was charged.
1002     */
1003    public abstract int getDischargeAmountScreenOnSinceCharge();
1004
1005    /**
1006     * Get the amount the battery has discharged while the screen was off,
1007     * since the last time power was unplugged.
1008     */
1009    public abstract int getDischargeAmountScreenOff();
1010
1011    /**
1012     * Get the amount the battery has discharged while the screen was off,
1013     * since the last time the device was charged.
1014     */
1015    public abstract int getDischargeAmountScreenOffSinceCharge();
1016
1017    /**
1018     * Returns the total, last, or current battery uptime in microseconds.
1019     *
1020     * @param curTime the elapsed realtime in microseconds.
1021     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1022     */
1023    public abstract long computeBatteryUptime(long curTime, int which);
1024
1025    /**
1026     * Returns the total, last, or current battery realtime in microseconds.
1027     *
1028     * @param curTime the current elapsed realtime in microseconds.
1029     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1030     */
1031    public abstract long computeBatteryRealtime(long curTime, int which);
1032
1033    /**
1034     * Returns the total, last, or current uptime in microseconds.
1035     *
1036     * @param curTime the current elapsed realtime in microseconds.
1037     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1038     */
1039    public abstract long computeUptime(long curTime, int which);
1040
1041    /**
1042     * Returns the total, last, or current realtime in microseconds.
1043     * *
1044     * @param curTime the current elapsed realtime in microseconds.
1045     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1046     */
1047    public abstract long computeRealtime(long curTime, int which);
1048
1049    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
1050
1051    /** Returns the number of different speeds that the CPU can run at */
1052    public abstract int getCpuSpeedSteps();
1053
1054    private final static void formatTimeRaw(StringBuilder out, long seconds) {
1055        long days = seconds / (60 * 60 * 24);
1056        if (days != 0) {
1057            out.append(days);
1058            out.append("d ");
1059        }
1060        long used = days * 60 * 60 * 24;
1061
1062        long hours = (seconds - used) / (60 * 60);
1063        if (hours != 0 || used != 0) {
1064            out.append(hours);
1065            out.append("h ");
1066        }
1067        used += hours * 60 * 60;
1068
1069        long mins = (seconds-used) / 60;
1070        if (mins != 0 || used != 0) {
1071            out.append(mins);
1072            out.append("m ");
1073        }
1074        used += mins * 60;
1075
1076        if (seconds != 0 || used != 0) {
1077            out.append(seconds-used);
1078            out.append("s ");
1079        }
1080    }
1081
1082    private final static void formatTime(StringBuilder sb, long time) {
1083        long sec = time / 100;
1084        formatTimeRaw(sb, sec);
1085        sb.append((time - (sec * 100)) * 10);
1086        sb.append("ms ");
1087    }
1088
1089    private final static void formatTimeMs(StringBuilder sb, long time) {
1090        long sec = time / 1000;
1091        formatTimeRaw(sb, sec);
1092        sb.append(time - (sec * 1000));
1093        sb.append("ms ");
1094    }
1095
1096    private final String formatRatioLocked(long num, long den) {
1097        if (den == 0L) {
1098            return "---%";
1099        }
1100        float perc = ((float)num) / ((float)den) * 100;
1101        mFormatBuilder.setLength(0);
1102        mFormatter.format("%.1f%%", perc);
1103        return mFormatBuilder.toString();
1104    }
1105
1106    private final String formatBytesLocked(long bytes) {
1107        mFormatBuilder.setLength(0);
1108
1109        if (bytes < BYTES_PER_KB) {
1110            return bytes + "B";
1111        } else if (bytes < BYTES_PER_MB) {
1112            mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
1113            return mFormatBuilder.toString();
1114        } else if (bytes < BYTES_PER_GB){
1115            mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
1116            return mFormatBuilder.toString();
1117        } else {
1118            mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
1119            return mFormatBuilder.toString();
1120        }
1121    }
1122
1123    private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
1124        if (timer != null) {
1125            // Convert from microseconds to milliseconds with rounding
1126            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
1127            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
1128            return totalTimeMillis;
1129        }
1130        return 0;
1131    }
1132
1133    /**
1134     *
1135     * @param sb a StringBuilder object.
1136     * @param timer a Timer object contining the wakelock times.
1137     * @param batteryRealtime the current on-battery time in microseconds.
1138     * @param name the name of the wakelock.
1139     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1140     * @param linePrefix a String to be prepended to each line of output.
1141     * @return the line prefix
1142     */
1143    private static final String printWakeLock(StringBuilder sb, Timer timer,
1144            long batteryRealtime, String name, int which, String linePrefix) {
1145
1146        if (timer != null) {
1147            long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1148
1149            int count = timer.getCountLocked(which);
1150            if (totalTimeMillis != 0) {
1151                sb.append(linePrefix);
1152                formatTimeMs(sb, totalTimeMillis);
1153                if (name != null) {
1154                    sb.append(name);
1155                    sb.append(' ');
1156                }
1157                sb.append('(');
1158                sb.append(count);
1159                sb.append(" times)");
1160                return ", ";
1161            }
1162        }
1163        return linePrefix;
1164    }
1165
1166    /**
1167     * Checkin version of wakelock printer. Prints simple comma-separated list.
1168     *
1169     * @param sb a StringBuilder object.
1170     * @param timer a Timer object contining the wakelock times.
1171     * @param now the current time in microseconds.
1172     * @param name the name of the wakelock.
1173     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1174     * @param linePrefix a String to be prepended to each line of output.
1175     * @return the line prefix
1176     */
1177    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
1178            String name, int which, String linePrefix) {
1179        long totalTimeMicros = 0;
1180        int count = 0;
1181        if (timer != null) {
1182            totalTimeMicros = timer.getTotalTimeLocked(now, which);
1183            count = timer.getCountLocked(which);
1184        }
1185        sb.append(linePrefix);
1186        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
1187        sb.append(',');
1188        sb.append(name != null ? name + "," : "");
1189        sb.append(count);
1190        return ",";
1191    }
1192
1193    /**
1194     * Dump a comma-separated line of values for terse checkin mode.
1195     *
1196     * @param pw the PageWriter to dump log to
1197     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
1198     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
1199     * @param args type-dependent data arguments
1200     */
1201    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
1202           Object... args ) {
1203        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
1204        pw.print(uid); pw.print(',');
1205        pw.print(category); pw.print(',');
1206        pw.print(type);
1207
1208        for (Object arg : args) {
1209            pw.print(',');
1210            pw.print(arg);
1211        }
1212        pw.print('\n');
1213    }
1214
1215    /**
1216     * Checkin server version of dump to produce more compact, computer-readable log.
1217     *
1218     * NOTE: all times are expressed in 'ms'.
1219     */
1220    public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
1221        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1222        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1223        final long batteryUptime = getBatteryUptime(rawUptime);
1224        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1225        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1226        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1227        final long totalRealtime = computeRealtime(rawRealtime, which);
1228        final long totalUptime = computeUptime(rawUptime, which);
1229        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1230        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1231        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1232        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1233        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1234
1235        StringBuilder sb = new StringBuilder(128);
1236
1237        SparseArray<? extends Uid> uidStats = getUidStats();
1238        final int NU = uidStats.size();
1239
1240        String category = STAT_NAMES[which];
1241
1242        // Dump "battery" stat
1243        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
1244                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
1245                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
1246                totalRealtime / 1000, totalUptime / 1000);
1247
1248        // Calculate total network and wakelock times across all uids.
1249        long rxTotal = 0;
1250        long txTotal = 0;
1251        long fullWakeLockTimeTotal = 0;
1252        long partialWakeLockTimeTotal = 0;
1253
1254        for (int iu = 0; iu < NU; iu++) {
1255            Uid u = uidStats.valueAt(iu);
1256            rxTotal += u.getTcpBytesReceived(which);
1257            txTotal += u.getTcpBytesSent(which);
1258
1259            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1260            if (wakelocks.size() > 0) {
1261                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1262                        : wakelocks.entrySet()) {
1263                    Uid.Wakelock wl = ent.getValue();
1264
1265                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1266                    if (fullWakeTimer != null) {
1267                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
1268                    }
1269
1270                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1271                    if (partialWakeTimer != null) {
1272                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
1273                            batteryRealtime, which);
1274                    }
1275                }
1276            }
1277        }
1278
1279        // Dump misc stats
1280        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
1281                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
1282                wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
1283                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
1284                getInputEventCount(which));
1285
1286        // Dump screen brightness stats
1287        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
1288        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1289            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
1290        }
1291        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
1292
1293        // Dump signal strength stats
1294        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1295        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1296            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
1297        }
1298        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
1299        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
1300                getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1301        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1302            args[i] = getPhoneSignalStrengthCount(i, which);
1303        }
1304        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
1305
1306        // Dump network type stats
1307        args = new Object[NUM_DATA_CONNECTION_TYPES];
1308        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1309            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
1310        }
1311        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
1312        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1313            args[i] = getPhoneDataConnectionCount(i, which);
1314        }
1315        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
1316
1317        if (which == STATS_SINCE_UNPLUGGED) {
1318            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
1319                    getDischargeCurrentLevel());
1320        }
1321
1322        if (which == STATS_SINCE_UNPLUGGED) {
1323            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1324                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1325                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1326                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1327        } else {
1328            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1329                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
1330                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1331        }
1332
1333        if (reqUid < 0) {
1334            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1335            if (kernelWakelocks.size() > 0) {
1336                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1337                    sb.setLength(0);
1338                    printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
1339
1340                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
1341                            sb.toString());
1342                }
1343            }
1344        }
1345
1346        for (int iu = 0; iu < NU; iu++) {
1347            final int uid = uidStats.keyAt(iu);
1348            if (reqUid >= 0 && uid != reqUid) {
1349                continue;
1350            }
1351            Uid u = uidStats.valueAt(iu);
1352            // Dump Network stats per uid, if any
1353            long rx = u.getTcpBytesReceived(which);
1354            long tx = u.getTcpBytesSent(which);
1355            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1356            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1357            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1358
1359            if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
1360
1361            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1362                    || uidWifiRunningTime != 0) {
1363                dumpLine(pw, uid, category, WIFI_DATA,
1364                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime);
1365            }
1366
1367            if (u.hasUserActivity()) {
1368                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
1369                boolean hasData = false;
1370                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1371                    int val = u.getUserActivityCount(i, which);
1372                    args[i] = val;
1373                    if (val != 0) hasData = true;
1374                }
1375                if (hasData) {
1376                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
1377                }
1378            }
1379
1380            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1381            if (wakelocks.size() > 0) {
1382                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1383                        : wakelocks.entrySet()) {
1384                    Uid.Wakelock wl = ent.getValue();
1385                    String linePrefix = "";
1386                    sb.setLength(0);
1387                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
1388                            batteryRealtime, "f", which, linePrefix);
1389                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
1390                            batteryRealtime, "p", which, linePrefix);
1391                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
1392                            batteryRealtime, "w", which, linePrefix);
1393
1394                    // Only log if we had at lease one wakelock...
1395                    if (sb.length() > 0) {
1396                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
1397                    }
1398                }
1399            }
1400
1401            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1402            if (sensors.size() > 0)  {
1403                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1404                        : sensors.entrySet()) {
1405                    Uid.Sensor se = ent.getValue();
1406                    int sensorNumber = ent.getKey();
1407                    Timer timer = se.getSensorTime();
1408                    if (timer != null) {
1409                        // Convert from microseconds to milliseconds with rounding
1410                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1411                        int count = timer.getCountLocked(which);
1412                        if (totalTime != 0) {
1413                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1414                        }
1415                    }
1416                }
1417            }
1418
1419            Timer vibTimer = u.getVibratorOnTimer();
1420            if (vibTimer != null) {
1421                // Convert from microseconds to milliseconds with rounding
1422                long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1423                int count = vibTimer.getCountLocked(which);
1424                if (totalTime != 0) {
1425                    dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
1426                }
1427            }
1428
1429            Timer fgTimer = u.getForegroundActivityTimer();
1430            if (fgTimer != null) {
1431                // Convert from microseconds to milliseconds with rounding
1432                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1433                int count = fgTimer.getCountLocked(which);
1434                if (totalTime != 0) {
1435                    dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
1436                }
1437            }
1438
1439            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1440            if (processStats.size() > 0) {
1441                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1442                        : processStats.entrySet()) {
1443                    Uid.Proc ps = ent.getValue();
1444
1445                    final long userMillis = ps.getUserTime(which) * 10;
1446                    final long systemMillis = ps.getSystemTime(which) * 10;
1447                    final long foregroundMillis = ps.getForegroundTime(which) * 10;
1448                    final long starts = ps.getStarts(which);
1449
1450                    if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
1451                            || starts != 0) {
1452                        dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
1453                                systemMillis, foregroundMillis, starts);
1454                    }
1455                }
1456            }
1457
1458            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1459            if (packageStats.size() > 0) {
1460                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1461                        : packageStats.entrySet()) {
1462
1463                    Uid.Pkg ps = ent.getValue();
1464                    int wakeups = ps.getWakeups(which);
1465                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1466                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1467                            : serviceStats.entrySet()) {
1468                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1469                        long startTime = ss.getStartTime(batteryUptime, which);
1470                        int starts = ss.getStarts(which);
1471                        int launches = ss.getLaunches(which);
1472                        if (startTime != 0 || starts != 0 || launches != 0) {
1473                            dumpLine(pw, uid, category, APK_DATA,
1474                                    wakeups, // wakeup alarms
1475                                    ent.getKey(), // Apk
1476                                    sent.getKey(), // service
1477                                    startTime / 1000, // time spent started, in ms
1478                                    starts,
1479                                    launches);
1480                        }
1481                    }
1482                }
1483            }
1484        }
1485    }
1486
1487    static final class TimerEntry {
1488        final String mName;
1489        final int mId;
1490        final BatteryStats.Timer mTimer;
1491        final long mTime;
1492        TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
1493            mName = name;
1494            mId = id;
1495            mTimer = timer;
1496            mTime = time;
1497        }
1498    }
1499
1500    @SuppressWarnings("unused")
1501    public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
1502        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1503        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1504        final long batteryUptime = getBatteryUptime(rawUptime);
1505        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1506
1507        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1508        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1509        final long totalRealtime = computeRealtime(rawRealtime, which);
1510        final long totalUptime = computeUptime(rawUptime, which);
1511
1512        StringBuilder sb = new StringBuilder(128);
1513
1514        SparseArray<? extends Uid> uidStats = getUidStats();
1515        final int NU = uidStats.size();
1516
1517        sb.setLength(0);
1518        sb.append(prefix);
1519                sb.append("  Time on battery: ");
1520                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
1521                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
1522                sb.append(") realtime, ");
1523                formatTimeMs(sb, whichBatteryUptime / 1000);
1524                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
1525                sb.append(") uptime");
1526        pw.println(sb.toString());
1527        sb.setLength(0);
1528        sb.append(prefix);
1529                sb.append("  Total run time: ");
1530                formatTimeMs(sb, totalRealtime / 1000);
1531                sb.append("realtime, ");
1532                formatTimeMs(sb, totalUptime / 1000);
1533                sb.append("uptime, ");
1534        pw.println(sb.toString());
1535
1536        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1537        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1538        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1539        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1540        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1541        sb.setLength(0);
1542        sb.append(prefix);
1543                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
1544                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
1545                sb.append("), Input events: "); sb.append(getInputEventCount(which));
1546                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
1547                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
1548                sb.append(")");
1549        pw.println(sb.toString());
1550        sb.setLength(0);
1551        sb.append(prefix);
1552        sb.append("  Screen brightnesses: ");
1553        boolean didOne = false;
1554        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1555            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
1556            if (time == 0) {
1557                continue;
1558            }
1559            if (didOne) sb.append(", ");
1560            didOne = true;
1561            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
1562            sb.append(" ");
1563            formatTimeMs(sb, time/1000);
1564            sb.append("(");
1565            sb.append(formatRatioLocked(time, screenOnTime));
1566            sb.append(")");
1567        }
1568        if (!didOne) sb.append("No activity");
1569        pw.println(sb.toString());
1570
1571        // Calculate total network and wakelock times across all uids.
1572        long rxTotal = 0;
1573        long txTotal = 0;
1574        long fullWakeLockTimeTotalMicros = 0;
1575        long partialWakeLockTimeTotalMicros = 0;
1576
1577        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
1578            @Override
1579            public int compare(TimerEntry lhs, TimerEntry rhs) {
1580                long lhsTime = lhs.mTime;
1581                long rhsTime = rhs.mTime;
1582                if (lhsTime < rhsTime) {
1583                    return 1;
1584                }
1585                if (lhsTime > rhsTime) {
1586                    return -1;
1587                }
1588                return 0;
1589            }
1590        };
1591
1592        if (reqUid < 0) {
1593            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1594            if (kernelWakelocks.size() > 0) {
1595                final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1596                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1597                    BatteryStats.Timer timer = ent.getValue();
1598                    long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1599                    if (totalTimeMillis > 0) {
1600                        timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
1601                    }
1602                }
1603                Collections.sort(timers, timerComparator);
1604                for (int i=0; i<timers.size(); i++) {
1605                    TimerEntry timer = timers.get(i);
1606                    String linePrefix = ": ";
1607                    sb.setLength(0);
1608                    sb.append(prefix);
1609                    sb.append("  Kernel Wake lock ");
1610                    sb.append(timer.mName);
1611                    linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
1612                            which, linePrefix);
1613                    if (!linePrefix.equals(": ")) {
1614                        sb.append(" realtime");
1615                        // Only print out wake locks that were held
1616                        pw.println(sb.toString());
1617                    }
1618                }
1619            }
1620        }
1621
1622        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1623
1624        for (int iu = 0; iu < NU; iu++) {
1625            Uid u = uidStats.valueAt(iu);
1626            rxTotal += u.getTcpBytesReceived(which);
1627            txTotal += u.getTcpBytesSent(which);
1628
1629            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1630            if (wakelocks.size() > 0) {
1631                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1632                        : wakelocks.entrySet()) {
1633                    Uid.Wakelock wl = ent.getValue();
1634
1635                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1636                    if (fullWakeTimer != null) {
1637                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
1638                                batteryRealtime, which);
1639                    }
1640
1641                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1642                    if (partialWakeTimer != null) {
1643                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
1644                                batteryRealtime, which);
1645                        if (totalTimeMicros > 0) {
1646                            if (reqUid < 0) {
1647                                // Only show the ordered list of all wake
1648                                // locks if the caller is not asking for data
1649                                // about a specific uid.
1650                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
1651                                        partialWakeTimer, totalTimeMicros));
1652                            }
1653                            partialWakeLockTimeTotalMicros += totalTimeMicros;
1654                        }
1655                    }
1656                }
1657            }
1658        }
1659
1660        pw.print(prefix);
1661                pw.print("  Total received: "); pw.print(formatBytesLocked(rxTotal));
1662                pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
1663        sb.setLength(0);
1664        sb.append(prefix);
1665                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
1666                        (fullWakeLockTimeTotalMicros + 500) / 1000);
1667                sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
1668                        (partialWakeLockTimeTotalMicros + 500) / 1000);
1669        pw.println(sb.toString());
1670
1671        sb.setLength(0);
1672        sb.append(prefix);
1673        sb.append("  Signal levels: ");
1674        didOne = false;
1675        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1676            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1677            if (time == 0) {
1678                continue;
1679            }
1680            if (didOne) sb.append(", ");
1681            didOne = true;
1682            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
1683            sb.append(" ");
1684            formatTimeMs(sb, time/1000);
1685            sb.append("(");
1686            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1687            sb.append(") ");
1688            sb.append(getPhoneSignalStrengthCount(i, which));
1689            sb.append("x");
1690        }
1691        if (!didOne) sb.append("No activity");
1692        pw.println(sb.toString());
1693
1694        sb.setLength(0);
1695        sb.append(prefix);
1696        sb.append("  Signal scanning time: ");
1697        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1698        pw.println(sb.toString());
1699
1700        sb.setLength(0);
1701        sb.append(prefix);
1702        sb.append("  Radio types: ");
1703        didOne = false;
1704        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1705            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1706            if (time == 0) {
1707                continue;
1708            }
1709            if (didOne) sb.append(", ");
1710            didOne = true;
1711            sb.append(DATA_CONNECTION_NAMES[i]);
1712            sb.append(" ");
1713            formatTimeMs(sb, time/1000);
1714            sb.append("(");
1715            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1716            sb.append(") ");
1717            sb.append(getPhoneDataConnectionCount(i, which));
1718            sb.append("x");
1719        }
1720        if (!didOne) sb.append("No activity");
1721        pw.println(sb.toString());
1722
1723        sb.setLength(0);
1724        sb.append(prefix);
1725        sb.append("  Radio data uptime when unplugged: ");
1726        sb.append(getRadioDataUptime() / 1000);
1727        sb.append(" ms");
1728        pw.println(sb.toString());
1729
1730        sb.setLength(0);
1731        sb.append(prefix);
1732                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
1733                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
1734                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
1735                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
1736                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
1737                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
1738                sb.append(")");
1739        pw.println(sb.toString());
1740
1741        pw.println(" ");
1742
1743        if (which == STATS_SINCE_UNPLUGGED) {
1744            if (getIsOnBattery()) {
1745                pw.print(prefix); pw.println("  Device is currently unplugged");
1746                pw.print(prefix); pw.print("    Discharge cycle start level: ");
1747                        pw.println(getDischargeStartLevel());
1748                pw.print(prefix); pw.print("    Discharge cycle current level: ");
1749                        pw.println(getDischargeCurrentLevel());
1750            } else {
1751                pw.print(prefix); pw.println("  Device is currently plugged into power");
1752                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
1753                        pw.println(getDischargeStartLevel());
1754                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
1755                        pw.println(getDischargeCurrentLevel());
1756            }
1757            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1758                    pw.println(getDischargeAmountScreenOn());
1759            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1760                    pw.println(getDischargeAmountScreenOff());
1761            pw.println(" ");
1762        } else {
1763            pw.print(prefix); pw.println("  Device battery use since last full charge");
1764            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
1765                    pw.println(getLowDischargeAmountSinceCharge());
1766            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
1767                    pw.println(getHighDischargeAmountSinceCharge());
1768            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1769                    pw.println(getDischargeAmountScreenOnSinceCharge());
1770            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1771                    pw.println(getDischargeAmountScreenOffSinceCharge());
1772            pw.println();
1773        }
1774
1775        if (timers.size() > 0) {
1776            Collections.sort(timers, timerComparator);
1777            pw.print(prefix); pw.println("  All partial wake locks:");
1778            for (int i=0; i<timers.size(); i++) {
1779                TimerEntry timer = timers.get(i);
1780                sb.setLength(0);
1781                sb.append("  Wake lock #");
1782                sb.append(timer.mId);
1783                sb.append(" ");
1784                sb.append(timer.mName);
1785                printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
1786                sb.append(" realtime");
1787                pw.println(sb.toString());
1788            }
1789            timers.clear();
1790            pw.println();
1791        }
1792
1793        for (int iu=0; iu<NU; iu++) {
1794            final int uid = uidStats.keyAt(iu);
1795            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
1796                continue;
1797            }
1798
1799            Uid u = uidStats.valueAt(iu);
1800
1801            pw.println(prefix + "  #" + uid + ":");
1802            boolean uidActivity = false;
1803
1804            long tcpReceived = u.getTcpBytesReceived(which);
1805            long tcpSent = u.getTcpBytesSent(which);
1806            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1807            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
1808            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1809
1810            if (tcpReceived != 0 || tcpSent != 0) {
1811                pw.print(prefix); pw.print("    Network: ");
1812                        pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
1813                        pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
1814            }
1815
1816            if (u.hasUserActivity()) {
1817                boolean hasData = false;
1818                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1819                    int val = u.getUserActivityCount(i, which);
1820                    if (val != 0) {
1821                        if (!hasData) {
1822                            sb.setLength(0);
1823                            sb.append("    User activity: ");
1824                            hasData = true;
1825                        } else {
1826                            sb.append(", ");
1827                        }
1828                        sb.append(val);
1829                        sb.append(" ");
1830                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1831                    }
1832                }
1833                if (hasData) {
1834                    pw.println(sb.toString());
1835                }
1836            }
1837
1838            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
1839                    || uidWifiRunningTime != 0) {
1840                sb.setLength(0);
1841                sb.append(prefix); sb.append("    Wifi Running: ");
1842                        formatTimeMs(sb, uidWifiRunningTime / 1000);
1843                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
1844                                whichBatteryRealtime)); sb.append(")\n");
1845                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1846                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1847                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1848                                whichBatteryRealtime)); sb.append(")\n");
1849                sb.append(prefix); sb.append("    Wifi Scan: ");
1850                        formatTimeMs(sb, wifiScanTime / 1000);
1851                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
1852                                whichBatteryRealtime)); sb.append(")");
1853                pw.println(sb.toString());
1854            }
1855
1856            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1857            if (wakelocks.size() > 0) {
1858                long totalFull = 0, totalPartial = 0, totalWindow = 0;
1859                int count = 0;
1860                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1861                    : wakelocks.entrySet()) {
1862                    Uid.Wakelock wl = ent.getValue();
1863                    String linePrefix = ": ";
1864                    sb.setLength(0);
1865                    sb.append(prefix);
1866                    sb.append("    Wake lock ");
1867                    sb.append(ent.getKey());
1868                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
1869                            "full", which, linePrefix);
1870                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
1871                            "partial", which, linePrefix);
1872                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
1873                            "window", which, linePrefix);
1874                    if (!linePrefix.equals(": ")) {
1875                        sb.append(" realtime");
1876                        // Only print out wake locks that were held
1877                        pw.println(sb.toString());
1878                        uidActivity = true;
1879                        count++;
1880                    }
1881                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
1882                            batteryRealtime, which);
1883                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
1884                            batteryRealtime, which);
1885                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
1886                            batteryRealtime, which);
1887                }
1888                if (count > 1) {
1889                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
1890                        sb.setLength(0);
1891                        sb.append(prefix);
1892                        sb.append("    TOTAL wake: ");
1893                        boolean needComma = false;
1894                        if (totalFull != 0) {
1895                            needComma = true;
1896                            formatTimeMs(sb, totalFull);
1897                            sb.append("full");
1898                        }
1899                        if (totalPartial != 0) {
1900                            if (needComma) {
1901                                sb.append(", ");
1902                            }
1903                            needComma = true;
1904                            formatTimeMs(sb, totalPartial);
1905                            sb.append("partial");
1906                        }
1907                        if (totalWindow != 0) {
1908                            if (needComma) {
1909                                sb.append(", ");
1910                            }
1911                            needComma = true;
1912                            formatTimeMs(sb, totalWindow);
1913                            sb.append("window");
1914                        }
1915                        sb.append(" realtime");
1916                        pw.println(sb.toString());
1917                    }
1918                }
1919            }
1920
1921            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1922            if (sensors.size() > 0) {
1923                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1924                    : sensors.entrySet()) {
1925                    Uid.Sensor se = ent.getValue();
1926                    int sensorNumber = ent.getKey();
1927                    sb.setLength(0);
1928                    sb.append(prefix);
1929                    sb.append("    Sensor ");
1930                    int handle = se.getHandle();
1931                    if (handle == Uid.Sensor.GPS) {
1932                        sb.append("GPS");
1933                    } else {
1934                        sb.append(handle);
1935                    }
1936                    sb.append(": ");
1937
1938                    Timer timer = se.getSensorTime();
1939                    if (timer != null) {
1940                        // Convert from microseconds to milliseconds with rounding
1941                        long totalTime = (timer.getTotalTimeLocked(
1942                                batteryRealtime, which) + 500) / 1000;
1943                        int count = timer.getCountLocked(which);
1944                        //timer.logState();
1945                        if (totalTime != 0) {
1946                            formatTimeMs(sb, totalTime);
1947                            sb.append("realtime (");
1948                            sb.append(count);
1949                            sb.append(" times)");
1950                        } else {
1951                            sb.append("(not used)");
1952                        }
1953                    } else {
1954                        sb.append("(not used)");
1955                    }
1956
1957                    pw.println(sb.toString());
1958                    uidActivity = true;
1959                }
1960            }
1961
1962            Timer vibTimer = u.getVibratorOnTimer();
1963            if (vibTimer != null) {
1964                // Convert from microseconds to milliseconds with rounding
1965                long totalTime = (vibTimer.getTotalTimeLocked(
1966                        batteryRealtime, which) + 500) / 1000;
1967                int count = vibTimer.getCountLocked(which);
1968                //timer.logState();
1969                if (totalTime != 0) {
1970                    sb.setLength(0);
1971                    sb.append(prefix);
1972                    sb.append("    Vibrator: ");
1973                    formatTimeMs(sb, totalTime);
1974                    sb.append("realtime (");
1975                    sb.append(count);
1976                    sb.append(" times)");
1977                    pw.println(sb.toString());
1978                    uidActivity = true;
1979                }
1980            }
1981
1982            Timer fgTimer = u.getForegroundActivityTimer();
1983            if (fgTimer != null) {
1984                // Convert from microseconds to milliseconds with rounding
1985                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1986                int count = fgTimer.getCountLocked(which);
1987                if (totalTime != 0) {
1988                    sb.setLength(0);
1989                    sb.append(prefix);
1990                    sb.append("    Foreground activities: ");
1991                    formatTimeMs(sb, totalTime);
1992                    sb.append("realtime (");
1993                    sb.append(count);
1994                    sb.append(" times)");
1995                    pw.println(sb.toString());
1996                    uidActivity = true;
1997                }
1998            }
1999
2000            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
2001            if (processStats.size() > 0) {
2002                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
2003                    : processStats.entrySet()) {
2004                    Uid.Proc ps = ent.getValue();
2005                    long userTime;
2006                    long systemTime;
2007                    long foregroundTime;
2008                    int starts;
2009                    int numExcessive;
2010
2011                    userTime = ps.getUserTime(which);
2012                    systemTime = ps.getSystemTime(which);
2013                    foregroundTime = ps.getForegroundTime(which);
2014                    starts = ps.getStarts(which);
2015                    numExcessive = which == STATS_SINCE_CHARGED
2016                            ? ps.countExcessivePowers() : 0;
2017
2018                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
2019                            || numExcessive != 0) {
2020                        sb.setLength(0);
2021                        sb.append(prefix); sb.append("    Proc ");
2022                                sb.append(ent.getKey()); sb.append(":\n");
2023                        sb.append(prefix); sb.append("      CPU: ");
2024                                formatTime(sb, userTime); sb.append("usr + ");
2025                                formatTime(sb, systemTime); sb.append("krn ; ");
2026                                formatTime(sb, foregroundTime); sb.append("fg");
2027                        if (starts != 0) {
2028                            sb.append("\n"); sb.append(prefix); sb.append("      ");
2029                                    sb.append(starts); sb.append(" proc starts");
2030                        }
2031                        pw.println(sb.toString());
2032                        for (int e=0; e<numExcessive; e++) {
2033                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
2034                            if (ew != null) {
2035                                pw.print(prefix); pw.print("      * Killed for ");
2036                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
2037                                            pw.print("wake lock");
2038                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
2039                                            pw.print("cpu");
2040                                        } else {
2041                                            pw.print("unknown");
2042                                        }
2043                                        pw.print(" use: ");
2044                                        TimeUtils.formatDuration(ew.usedTime, pw);
2045                                        pw.print(" over ");
2046                                        TimeUtils.formatDuration(ew.overTime, pw);
2047                                        pw.print(" (");
2048                                        pw.print((ew.usedTime*100)/ew.overTime);
2049                                        pw.println("%)");
2050                            }
2051                        }
2052                        uidActivity = true;
2053                    }
2054                }
2055            }
2056
2057            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
2058            if (packageStats.size() > 0) {
2059                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
2060                    : packageStats.entrySet()) {
2061                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
2062                    boolean apkActivity = false;
2063                    Uid.Pkg ps = ent.getValue();
2064                    int wakeups = ps.getWakeups(which);
2065                    if (wakeups != 0) {
2066                        pw.print(prefix); pw.print("      ");
2067                                pw.print(wakeups); pw.println(" wakeup alarms");
2068                        apkActivity = true;
2069                    }
2070                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
2071                    if (serviceStats.size() > 0) {
2072                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
2073                                : serviceStats.entrySet()) {
2074                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
2075                            long startTime = ss.getStartTime(batteryUptime, which);
2076                            int starts = ss.getStarts(which);
2077                            int launches = ss.getLaunches(which);
2078                            if (startTime != 0 || starts != 0 || launches != 0) {
2079                                sb.setLength(0);
2080                                sb.append(prefix); sb.append("      Service ");
2081                                        sb.append(sent.getKey()); sb.append(":\n");
2082                                sb.append(prefix); sb.append("        Created for: ");
2083                                        formatTimeMs(sb, startTime / 1000);
2084                                        sb.append("uptime\n");
2085                                sb.append(prefix); sb.append("        Starts: ");
2086                                        sb.append(starts);
2087                                        sb.append(", launches: "); sb.append(launches);
2088                                pw.println(sb.toString());
2089                                apkActivity = true;
2090                            }
2091                        }
2092                    }
2093                    if (!apkActivity) {
2094                        pw.print(prefix); pw.println("      (nothing executed)");
2095                    }
2096                    uidActivity = true;
2097                }
2098            }
2099            if (!uidActivity) {
2100                pw.print(prefix); pw.println("    (nothing executed)");
2101            }
2102        }
2103    }
2104
2105    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) {
2106        int diff = oldval ^ newval;
2107        if (diff == 0) return;
2108        for (int i=0; i<descriptions.length; i++) {
2109            BitDescription bd = descriptions[i];
2110            if ((diff&bd.mask) != 0) {
2111                if (bd.shift < 0) {
2112                    pw.print((newval&bd.mask) != 0 ? " +" : " -");
2113                    pw.print(bd.name);
2114                } else {
2115                    pw.print(" ");
2116                    pw.print(bd.name);
2117                    pw.print("=");
2118                    int val = (newval&bd.mask)>>bd.shift;
2119                    if (bd.values != null && val >= 0 && val < bd.values.length) {
2120                        pw.print(bd.values[val]);
2121                    } else {
2122                        pw.print(val);
2123                    }
2124                }
2125            }
2126        }
2127    }
2128
2129    public void prepareForDumpLocked() {
2130    }
2131
2132    public static class HistoryPrinter {
2133        int oldState = 0;
2134        int oldStatus = -1;
2135        int oldHealth = -1;
2136        int oldPlug = -1;
2137        int oldTemp = -1;
2138        int oldVolt = -1;
2139
2140        public void printNextItem(PrintWriter pw, HistoryItem rec, long now) {
2141            pw.print("  ");
2142            TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
2143            pw.print(" ");
2144            if (rec.cmd == HistoryItem.CMD_START) {
2145                pw.println(" START");
2146            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
2147                pw.println(" *OVERFLOW*");
2148            } else {
2149                if (rec.batteryLevel < 10) pw.print("00");
2150                else if (rec.batteryLevel < 100) pw.print("0");
2151                pw.print(rec.batteryLevel);
2152                pw.print(" ");
2153                if (rec.states < 0x10) pw.print("0000000");
2154                else if (rec.states < 0x100) pw.print("000000");
2155                else if (rec.states < 0x1000) pw.print("00000");
2156                else if (rec.states < 0x10000) pw.print("0000");
2157                else if (rec.states < 0x100000) pw.print("000");
2158                else if (rec.states < 0x1000000) pw.print("00");
2159                else if (rec.states < 0x10000000) pw.print("0");
2160                pw.print(Integer.toHexString(rec.states));
2161                if (oldStatus != rec.batteryStatus) {
2162                    oldStatus = rec.batteryStatus;
2163                    pw.print(" status=");
2164                    switch (oldStatus) {
2165                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
2166                            pw.print("unknown");
2167                            break;
2168                        case BatteryManager.BATTERY_STATUS_CHARGING:
2169                            pw.print("charging");
2170                            break;
2171                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
2172                            pw.print("discharging");
2173                            break;
2174                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
2175                            pw.print("not-charging");
2176                            break;
2177                        case BatteryManager.BATTERY_STATUS_FULL:
2178                            pw.print("full");
2179                            break;
2180                        default:
2181                            pw.print(oldStatus);
2182                            break;
2183                    }
2184                }
2185                if (oldHealth != rec.batteryHealth) {
2186                    oldHealth = rec.batteryHealth;
2187                    pw.print(" health=");
2188                    switch (oldHealth) {
2189                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
2190                            pw.print("unknown");
2191                            break;
2192                        case BatteryManager.BATTERY_HEALTH_GOOD:
2193                            pw.print("good");
2194                            break;
2195                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
2196                            pw.print("overheat");
2197                            break;
2198                        case BatteryManager.BATTERY_HEALTH_DEAD:
2199                            pw.print("dead");
2200                            break;
2201                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
2202                            pw.print("over-voltage");
2203                            break;
2204                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
2205                            pw.print("failure");
2206                            break;
2207                        default:
2208                            pw.print(oldHealth);
2209                            break;
2210                    }
2211                }
2212                if (oldPlug != rec.batteryPlugType) {
2213                    oldPlug = rec.batteryPlugType;
2214                    pw.print(" plug=");
2215                    switch (oldPlug) {
2216                        case 0:
2217                            pw.print("none");
2218                            break;
2219                        case BatteryManager.BATTERY_PLUGGED_AC:
2220                            pw.print("ac");
2221                            break;
2222                        case BatteryManager.BATTERY_PLUGGED_USB:
2223                            pw.print("usb");
2224                            break;
2225                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
2226                            pw.print("wireless");
2227                            break;
2228                        default:
2229                            pw.print(oldPlug);
2230                            break;
2231                    }
2232                }
2233                if (oldTemp != rec.batteryTemperature) {
2234                    oldTemp = rec.batteryTemperature;
2235                    pw.print(" temp=");
2236                    pw.print(oldTemp);
2237                }
2238                if (oldVolt != rec.batteryVoltage) {
2239                    oldVolt = rec.batteryVoltage;
2240                    pw.print(" volt=");
2241                    pw.print(oldVolt);
2242                }
2243                printBitDescriptions(pw, oldState, rec.states,
2244                        HISTORY_STATE_DESCRIPTIONS);
2245                pw.println();
2246            }
2247            oldState = rec.states;
2248        }
2249    }
2250
2251    /**
2252     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
2253     *
2254     * @param pw a Printer to receive the dump output.
2255     */
2256    @SuppressWarnings("unused")
2257    public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly) {
2258        prepareForDumpLocked();
2259
2260        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2261
2262        final HistoryItem rec = new HistoryItem();
2263        if (startIteratingHistoryLocked()) {
2264            pw.println("Battery History:");
2265            HistoryPrinter hprinter = new HistoryPrinter();
2266            while (getNextHistoryLocked(rec)) {
2267                hprinter.printNextItem(pw, rec, now);
2268            }
2269            finishIteratingHistoryLocked();
2270            pw.println("");
2271        }
2272
2273        if (startIteratingOldHistoryLocked()) {
2274            pw.println("Old battery History:");
2275            HistoryPrinter hprinter = new HistoryPrinter();
2276            while (getNextOldHistoryLocked(rec)) {
2277                hprinter.printNextItem(pw, rec, now);
2278            }
2279            finishIteratingOldHistoryLocked();
2280            pw.println("");
2281        }
2282
2283        SparseArray<? extends Uid> uidStats = getUidStats();
2284        final int NU = uidStats.size();
2285        boolean didPid = false;
2286        long nowRealtime = SystemClock.elapsedRealtime();
2287        for (int i=0; i<NU; i++) {
2288            Uid uid = uidStats.valueAt(i);
2289            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
2290            if (pids != null) {
2291                for (int j=0; j<pids.size(); j++) {
2292                    Uid.Pid pid = pids.valueAt(j);
2293                    if (!didPid) {
2294                        pw.println("Per-PID Stats:");
2295                        didPid = true;
2296                    }
2297                    long time = pid.mWakeSum + (pid.mWakeStart != 0
2298                            ? (nowRealtime - pid.mWakeStart) : 0);
2299                    pw.print("  PID "); pw.print(pids.keyAt(j));
2300                            pw.print(" wake time: ");
2301                            TimeUtils.formatDuration(time, pw);
2302                            pw.println("");
2303                }
2304            }
2305        }
2306        if (didPid) {
2307            pw.println("");
2308        }
2309
2310        if (!isUnpluggedOnly) {
2311            pw.println("Statistics since last charge:");
2312            pw.println("  System starts: " + getStartCount()
2313                    + ", currently on battery: " + getIsOnBattery());
2314            dumpLocked(pw, "", STATS_SINCE_CHARGED, -1);
2315            pw.println("");
2316        }
2317        pw.println("Statistics since last unplugged:");
2318        dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, -1);
2319    }
2320
2321    @SuppressWarnings("unused")
2322    public void dumpCheckinLocked(
2323            PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly) {
2324        prepareForDumpLocked();
2325
2326        if (apps != null) {
2327            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
2328            for (int i=0; i<apps.size(); i++) {
2329                ApplicationInfo ai = apps.get(i);
2330                ArrayList<String> pkgs = uids.get(ai.uid);
2331                if (pkgs == null) {
2332                    pkgs = new ArrayList<String>();
2333                    uids.put(ai.uid, pkgs);
2334                }
2335                pkgs.add(ai.packageName);
2336            }
2337            SparseArray<? extends Uid> uidStats = getUidStats();
2338            final int NU = uidStats.size();
2339            String[] lineArgs = new String[2];
2340            for (int i=0; i<NU; i++) {
2341                int uid = uidStats.keyAt(i);
2342                ArrayList<String> pkgs = uids.get(uid);
2343                if (pkgs != null) {
2344                    for (int j=0; j<pkgs.size(); j++) {
2345                        lineArgs[0] = Integer.toString(uid);
2346                        lineArgs[1] = pkgs.get(j);
2347                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
2348                                (Object[])lineArgs);
2349                    }
2350                }
2351            }
2352        }
2353        if (isUnpluggedOnly) {
2354            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2355        }
2356        else {
2357            dumpCheckinLocked(pw, STATS_SINCE_CHARGED, -1);
2358            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2359        }
2360    }
2361}
2362