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