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