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