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