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