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    private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
1099        if (timer != null) {
1100            // Convert from microseconds to milliseconds with rounding
1101            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
1102            long totalTimeMillis = (totalTimeMicros + 500) / 1000;
1103            return totalTimeMillis;
1104        }
1105        return 0;
1106    }
1107
1108    /**
1109     *
1110     * @param sb a StringBuilder object.
1111     * @param timer a Timer object contining the wakelock times.
1112     * @param batteryRealtime the current on-battery time in microseconds.
1113     * @param name the name of the wakelock.
1114     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1115     * @param linePrefix a String to be prepended to each line of output.
1116     * @return the line prefix
1117     */
1118    private static final String printWakeLock(StringBuilder sb, Timer timer,
1119            long batteryRealtime, String name, int which, String linePrefix) {
1120
1121        if (timer != null) {
1122            long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1123
1124            int count = timer.getCountLocked(which);
1125            if (totalTimeMillis != 0) {
1126                sb.append(linePrefix);
1127                formatTimeMs(sb, totalTimeMillis);
1128                if (name != null) sb.append(name);
1129                sb.append(' ');
1130                sb.append('(');
1131                sb.append(count);
1132                sb.append(" times)");
1133                return ", ";
1134            }
1135        }
1136        return linePrefix;
1137    }
1138
1139    /**
1140     * Checkin version of wakelock printer. Prints simple comma-separated list.
1141     *
1142     * @param sb a StringBuilder object.
1143     * @param timer a Timer object contining the wakelock times.
1144     * @param now the current time in microseconds.
1145     * @param name the name of the wakelock.
1146     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
1147     * @param linePrefix a String to be prepended to each line of output.
1148     * @return the line prefix
1149     */
1150    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
1151            String name, int which, String linePrefix) {
1152        long totalTimeMicros = 0;
1153        int count = 0;
1154        if (timer != null) {
1155            totalTimeMicros = timer.getTotalTimeLocked(now, which);
1156            count = timer.getCountLocked(which);
1157        }
1158        sb.append(linePrefix);
1159        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
1160        sb.append(',');
1161        sb.append(name != null ? name + "," : "");
1162        sb.append(count);
1163        return ",";
1164    }
1165
1166    /**
1167     * Dump a comma-separated line of values for terse checkin mode.
1168     *
1169     * @param pw the PageWriter to dump log to
1170     * @param category category of data (e.g. "total", "last", "unplugged", "current" )
1171     * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
1172     * @param args type-dependent data arguments
1173     */
1174    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
1175           Object... args ) {
1176        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
1177        pw.print(uid); pw.print(',');
1178        pw.print(category); pw.print(',');
1179        pw.print(type);
1180
1181        for (Object arg : args) {
1182            pw.print(',');
1183            pw.print(arg);
1184        }
1185        pw.print('\n');
1186    }
1187
1188    /**
1189     * Checkin server version of dump to produce more compact, computer-readable log.
1190     *
1191     * NOTE: all times are expressed in 'ms'.
1192     */
1193    public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
1194        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1195        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1196        final long batteryUptime = getBatteryUptime(rawUptime);
1197        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1198        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1199        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1200        final long totalRealtime = computeRealtime(rawRealtime, which);
1201        final long totalUptime = computeUptime(rawUptime, which);
1202        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1203        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1204        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1205        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1206        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1207
1208        StringBuilder sb = new StringBuilder(128);
1209
1210        SparseArray<? extends Uid> uidStats = getUidStats();
1211        final int NU = uidStats.size();
1212
1213        String category = STAT_NAMES[which];
1214
1215        // Dump "battery" stat
1216        dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
1217                which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
1218                whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
1219                totalRealtime / 1000, totalUptime / 1000);
1220
1221        // Calculate total network and wakelock times across all uids.
1222        long rxTotal = 0;
1223        long txTotal = 0;
1224        long fullWakeLockTimeTotal = 0;
1225        long partialWakeLockTimeTotal = 0;
1226
1227        for (int iu = 0; iu < NU; iu++) {
1228            Uid u = uidStats.valueAt(iu);
1229            rxTotal += u.getTcpBytesReceived(which);
1230            txTotal += u.getTcpBytesSent(which);
1231
1232            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1233            if (wakelocks.size() > 0) {
1234                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1235                        : wakelocks.entrySet()) {
1236                    Uid.Wakelock wl = ent.getValue();
1237
1238                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1239                    if (fullWakeTimer != null) {
1240                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
1241                    }
1242
1243                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1244                    if (partialWakeTimer != null) {
1245                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
1246                            batteryRealtime, which);
1247                    }
1248                }
1249            }
1250        }
1251
1252        // Dump misc stats
1253        dumpLine(pw, 0 /* uid */, category, MISC_DATA,
1254                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
1255                wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
1256                fullWakeLockTimeTotal, partialWakeLockTimeTotal,
1257                getInputEventCount(which));
1258
1259        // Dump screen brightness stats
1260        Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
1261        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1262            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
1263        }
1264        dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
1265
1266        // Dump signal strength stats
1267        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
1268        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1269            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
1270        }
1271        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
1272        dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
1273                getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1274        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1275            args[i] = getPhoneSignalStrengthCount(i, which);
1276        }
1277        dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
1278
1279        // Dump network type stats
1280        args = new Object[NUM_DATA_CONNECTION_TYPES];
1281        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1282            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
1283        }
1284        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
1285        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1286            args[i] = getPhoneDataConnectionCount(i, which);
1287        }
1288        dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
1289
1290        if (which == STATS_SINCE_UNPLUGGED) {
1291            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
1292                    getDischargeCurrentLevel());
1293        }
1294
1295        if (which == STATS_SINCE_UNPLUGGED) {
1296            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1297                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1298                    getDischargeStartLevel()-getDischargeCurrentLevel(),
1299                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1300        } else {
1301            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
1302                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
1303                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
1304        }
1305
1306        if (reqUid < 0) {
1307            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1308            if (kernelWakelocks.size() > 0) {
1309                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1310                    sb.setLength(0);
1311                    printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
1312
1313                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
1314                            sb.toString());
1315                }
1316            }
1317        }
1318
1319        for (int iu = 0; iu < NU; iu++) {
1320            final int uid = uidStats.keyAt(iu);
1321            if (reqUid >= 0 && uid != reqUid) {
1322                continue;
1323            }
1324            Uid u = uidStats.valueAt(iu);
1325            // Dump Network stats per uid, if any
1326            long rx = u.getTcpBytesReceived(which);
1327            long tx = u.getTcpBytesSent(which);
1328            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1329            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
1330            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1331
1332            if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
1333
1334            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
1335                    || uidWifiRunningTime != 0) {
1336                dumpLine(pw, uid, category, WIFI_LOCK_DATA,
1337                        fullWifiLockOnTime, scanWifiLockOnTime, uidWifiRunningTime);
1338            }
1339
1340            if (u.hasUserActivity()) {
1341                args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
1342                boolean hasData = false;
1343                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
1344                    int val = u.getUserActivityCount(i, which);
1345                    args[i] = val;
1346                    if (val != 0) hasData = true;
1347                }
1348                if (hasData) {
1349                    dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
1350                }
1351            }
1352
1353            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1354            if (wakelocks.size() > 0) {
1355                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1356                        : wakelocks.entrySet()) {
1357                    Uid.Wakelock wl = ent.getValue();
1358                    String linePrefix = "";
1359                    sb.setLength(0);
1360                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
1361                            batteryRealtime, "f", which, linePrefix);
1362                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
1363                            batteryRealtime, "p", which, linePrefix);
1364                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
1365                            batteryRealtime, "w", which, linePrefix);
1366
1367                    // Only log if we had at lease one wakelock...
1368                    if (sb.length() > 0) {
1369                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
1370                    }
1371                }
1372            }
1373
1374            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1375            if (sensors.size() > 0)  {
1376                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1377                        : sensors.entrySet()) {
1378                    Uid.Sensor se = ent.getValue();
1379                    int sensorNumber = ent.getKey();
1380                    Timer timer = se.getSensorTime();
1381                    if (timer != null) {
1382                        // Convert from microseconds to milliseconds with rounding
1383                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
1384                        int count = timer.getCountLocked(which);
1385                        if (totalTime != 0) {
1386                            dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
1387                        }
1388                    }
1389                }
1390            }
1391
1392            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1393            if (processStats.size() > 0) {
1394                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1395                        : processStats.entrySet()) {
1396                    Uid.Proc ps = ent.getValue();
1397
1398                    long userTime = ps.getUserTime(which);
1399                    long systemTime = ps.getSystemTime(which);
1400                    int starts = ps.getStarts(which);
1401
1402                    if (userTime != 0 || systemTime != 0 || starts != 0) {
1403                        dumpLine(pw, uid, category, PROCESS_DATA,
1404                                ent.getKey(), // proc
1405                                userTime * 10, // cpu time in ms
1406                                systemTime * 10, // user time in ms
1407                                starts); // process starts
1408                    }
1409                }
1410            }
1411
1412            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1413            if (packageStats.size() > 0) {
1414                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1415                        : packageStats.entrySet()) {
1416
1417                    Uid.Pkg ps = ent.getValue();
1418                    int wakeups = ps.getWakeups(which);
1419                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1420                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1421                            : serviceStats.entrySet()) {
1422                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1423                        long startTime = ss.getStartTime(batteryUptime, which);
1424                        int starts = ss.getStarts(which);
1425                        int launches = ss.getLaunches(which);
1426                        if (startTime != 0 || starts != 0 || launches != 0) {
1427                            dumpLine(pw, uid, category, APK_DATA,
1428                                    wakeups, // wakeup alarms
1429                                    ent.getKey(), // Apk
1430                                    sent.getKey(), // service
1431                                    startTime / 1000, // time spent started, in ms
1432                                    starts,
1433                                    launches);
1434                        }
1435                    }
1436                }
1437            }
1438        }
1439    }
1440
1441    @SuppressWarnings("unused")
1442    public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUid) {
1443        final long rawUptime = SystemClock.uptimeMillis() * 1000;
1444        final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
1445        final long batteryUptime = getBatteryUptime(rawUptime);
1446        final long batteryRealtime = getBatteryRealtime(rawRealtime);
1447
1448        final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
1449        final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
1450        final long totalRealtime = computeRealtime(rawRealtime, which);
1451        final long totalUptime = computeUptime(rawUptime, which);
1452
1453        StringBuilder sb = new StringBuilder(128);
1454
1455        SparseArray<? extends Uid> uidStats = getUidStats();
1456        final int NU = uidStats.size();
1457
1458        sb.setLength(0);
1459        sb.append(prefix);
1460                sb.append("  Time on battery: ");
1461                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
1462                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
1463                sb.append(") realtime, ");
1464                formatTimeMs(sb, whichBatteryUptime / 1000);
1465                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
1466                sb.append(") uptime");
1467        pw.println(sb.toString());
1468        sb.setLength(0);
1469        sb.append(prefix);
1470                sb.append("  Total run time: ");
1471                formatTimeMs(sb, totalRealtime / 1000);
1472                sb.append("realtime, ");
1473                formatTimeMs(sb, totalUptime / 1000);
1474                sb.append("uptime, ");
1475        pw.println(sb.toString());
1476
1477        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
1478        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
1479        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
1480        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
1481        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
1482        sb.setLength(0);
1483        sb.append(prefix);
1484                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
1485                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
1486                sb.append("), Input events: "); sb.append(getInputEventCount(which));
1487                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
1488                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
1489                sb.append(")");
1490        pw.println(sb.toString());
1491        sb.setLength(0);
1492        sb.append(prefix);
1493        sb.append("  Screen brightnesses: ");
1494        boolean didOne = false;
1495        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1496            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
1497            if (time == 0) {
1498                continue;
1499            }
1500            if (didOne) sb.append(", ");
1501            didOne = true;
1502            sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
1503            sb.append(" ");
1504            formatTimeMs(sb, time/1000);
1505            sb.append("(");
1506            sb.append(formatRatioLocked(time, screenOnTime));
1507            sb.append(")");
1508        }
1509        if (!didOne) sb.append("No activity");
1510        pw.println(sb.toString());
1511
1512        // Calculate total network and wakelock times across all uids.
1513        long rxTotal = 0;
1514        long txTotal = 0;
1515        long fullWakeLockTimeTotalMicros = 0;
1516        long partialWakeLockTimeTotalMicros = 0;
1517
1518        if (reqUid < 0) {
1519            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
1520            if (kernelWakelocks.size() > 0) {
1521                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1522
1523                    String linePrefix = ": ";
1524                    sb.setLength(0);
1525                    sb.append(prefix);
1526                    sb.append("  Kernel Wake lock ");
1527                    sb.append(ent.getKey());
1528                    linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which,
1529                            linePrefix);
1530                    if (!linePrefix.equals(": ")) {
1531                        sb.append(" realtime");
1532                        // Only print out wake locks that were held
1533                        pw.println(sb.toString());
1534                    }
1535                }
1536            }
1537        }
1538
1539        for (int iu = 0; iu < NU; iu++) {
1540            Uid u = uidStats.valueAt(iu);
1541            rxTotal += u.getTcpBytesReceived(which);
1542            txTotal += u.getTcpBytesSent(which);
1543
1544            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1545            if (wakelocks.size() > 0) {
1546                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1547                        : wakelocks.entrySet()) {
1548                    Uid.Wakelock wl = ent.getValue();
1549
1550                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
1551                    if (fullWakeTimer != null) {
1552                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
1553                                batteryRealtime, which);
1554                    }
1555
1556                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
1557                    if (partialWakeTimer != null) {
1558                        partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
1559                                batteryRealtime, which);
1560                    }
1561                }
1562            }
1563        }
1564
1565        pw.print(prefix);
1566                pw.print("  Total received: "); pw.print(formatBytesLocked(rxTotal));
1567                pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
1568        sb.setLength(0);
1569        sb.append(prefix);
1570                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
1571                        (fullWakeLockTimeTotalMicros + 500) / 1000);
1572                sb.append(", Total partial waklock time: "); formatTimeMs(sb,
1573                        (partialWakeLockTimeTotalMicros + 500) / 1000);
1574        pw.println(sb.toString());
1575
1576        sb.setLength(0);
1577        sb.append(prefix);
1578        sb.append("  Signal levels: ");
1579        didOne = false;
1580        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
1581            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
1582            if (time == 0) {
1583                continue;
1584            }
1585            if (didOne) sb.append(", ");
1586            didOne = true;
1587            sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
1588            sb.append(" ");
1589            formatTimeMs(sb, time/1000);
1590            sb.append("(");
1591            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1592            sb.append(") ");
1593            sb.append(getPhoneSignalStrengthCount(i, which));
1594            sb.append("x");
1595        }
1596        if (!didOne) sb.append("No activity");
1597        pw.println(sb.toString());
1598
1599        sb.setLength(0);
1600        sb.append(prefix);
1601        sb.append("  Signal scanning time: ");
1602        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
1603        pw.println(sb.toString());
1604
1605        sb.setLength(0);
1606        sb.append(prefix);
1607        sb.append("  Radio types: ");
1608        didOne = false;
1609        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1610            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
1611            if (time == 0) {
1612                continue;
1613            }
1614            if (didOne) sb.append(", ");
1615            didOne = true;
1616            sb.append(DATA_CONNECTION_NAMES[i]);
1617            sb.append(" ");
1618            formatTimeMs(sb, time/1000);
1619            sb.append("(");
1620            sb.append(formatRatioLocked(time, whichBatteryRealtime));
1621            sb.append(") ");
1622            sb.append(getPhoneDataConnectionCount(i, which));
1623            sb.append("x");
1624        }
1625        if (!didOne) sb.append("No activity");
1626        pw.println(sb.toString());
1627
1628        sb.setLength(0);
1629        sb.append(prefix);
1630        sb.append("  Radio data uptime when unplugged: ");
1631        sb.append(getRadioDataUptime() / 1000);
1632        sb.append(" ms");
1633        pw.println(sb.toString());
1634
1635        sb.setLength(0);
1636        sb.append(prefix);
1637                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
1638                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
1639                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
1640                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
1641                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
1642                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
1643                sb.append(")");
1644        pw.println(sb.toString());
1645
1646        pw.println(" ");
1647
1648        if (which == STATS_SINCE_UNPLUGGED) {
1649            if (getIsOnBattery()) {
1650                pw.print(prefix); pw.println("  Device is currently unplugged");
1651                pw.print(prefix); pw.print("    Discharge cycle start level: ");
1652                        pw.println(getDischargeStartLevel());
1653                pw.print(prefix); pw.print("    Discharge cycle current level: ");
1654                        pw.println(getDischargeCurrentLevel());
1655            } else {
1656                pw.print(prefix); pw.println("  Device is currently plugged into power");
1657                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
1658                        pw.println(getDischargeStartLevel());
1659                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
1660                        pw.println(getDischargeCurrentLevel());
1661            }
1662            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1663                    pw.println(getDischargeAmountScreenOn());
1664            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1665                    pw.println(getDischargeAmountScreenOff());
1666            pw.println(" ");
1667        } else {
1668            pw.print(prefix); pw.println("  Device battery use since last full charge");
1669            pw.print(prefix); pw.print("    Amount discharged (lower bound): ");
1670                    pw.println(getLowDischargeAmountSinceCharge());
1671            pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
1672                    pw.println(getHighDischargeAmountSinceCharge());
1673            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
1674                    pw.println(getDischargeAmountScreenOnSinceCharge());
1675            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
1676                    pw.println(getDischargeAmountScreenOffSinceCharge());
1677            pw.println(" ");
1678        }
1679
1680
1681        for (int iu=0; iu<NU; iu++) {
1682            final int uid = uidStats.keyAt(iu);
1683            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
1684                continue;
1685            }
1686
1687            Uid u = uidStats.valueAt(iu);
1688
1689            pw.println(prefix + "  #" + uid + ":");
1690            boolean uidActivity = false;
1691
1692            long tcpReceived = u.getTcpBytesReceived(which);
1693            long tcpSent = u.getTcpBytesSent(which);
1694            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
1695            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
1696            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
1697
1698            if (tcpReceived != 0 || tcpSent != 0) {
1699                pw.print(prefix); pw.print("    Network: ");
1700                        pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
1701                        pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
1702            }
1703
1704            if (u.hasUserActivity()) {
1705                boolean hasData = false;
1706                for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1707                    int val = u.getUserActivityCount(i, which);
1708                    if (val != 0) {
1709                        if (!hasData) {
1710                            sb.setLength(0);
1711                            sb.append("    User activity: ");
1712                            hasData = true;
1713                        } else {
1714                            sb.append(", ");
1715                        }
1716                        sb.append(val);
1717                        sb.append(" ");
1718                        sb.append(Uid.USER_ACTIVITY_TYPES[i]);
1719                    }
1720                }
1721                if (hasData) {
1722                    pw.println(sb.toString());
1723                }
1724            }
1725
1726            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
1727                    || uidWifiRunningTime != 0) {
1728                sb.setLength(0);
1729                sb.append(prefix); sb.append("    Wifi Running: ");
1730                        formatTimeMs(sb, uidWifiRunningTime / 1000);
1731                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
1732                                whichBatteryRealtime)); sb.append(")\n");
1733                sb.append(prefix); sb.append("    Full Wifi Lock: ");
1734                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
1735                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
1736                                whichBatteryRealtime)); sb.append(")\n");
1737                sb.append(prefix); sb.append("    Scan Wifi Lock: ");
1738                        formatTimeMs(sb, scanWifiLockOnTime / 1000);
1739                        sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime,
1740                                whichBatteryRealtime)); sb.append(")");
1741                pw.println(sb.toString());
1742            }
1743
1744            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
1745            if (wakelocks.size() > 0) {
1746                long totalFull = 0, totalPartial = 0, totalWindow = 0;
1747                int count = 0;
1748                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
1749                    : wakelocks.entrySet()) {
1750                    Uid.Wakelock wl = ent.getValue();
1751                    String linePrefix = ": ";
1752                    sb.setLength(0);
1753                    sb.append(prefix);
1754                    sb.append("    Wake lock ");
1755                    sb.append(ent.getKey());
1756                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
1757                            "full", which, linePrefix);
1758                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
1759                            "partial", which, linePrefix);
1760                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
1761                            "window", which, linePrefix);
1762                    if (!linePrefix.equals(": ")) {
1763                        sb.append(" realtime");
1764                        // Only print out wake locks that were held
1765                        pw.println(sb.toString());
1766                        uidActivity = true;
1767                        count++;
1768                    }
1769                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
1770                            batteryRealtime, which);
1771                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
1772                            batteryRealtime, which);
1773                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
1774                            batteryRealtime, which);
1775                }
1776                if (count > 1) {
1777                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
1778                        sb.setLength(0);
1779                        sb.append(prefix);
1780                        sb.append("    TOTAL wake: ");
1781                        boolean needComma = false;
1782                        if (totalFull != 0) {
1783                            needComma = true;
1784                            formatTimeMs(sb, totalFull);
1785                            sb.append("full");
1786                        }
1787                        if (totalPartial != 0) {
1788                            if (needComma) {
1789                                sb.append(", ");
1790                            }
1791                            needComma = true;
1792                            formatTimeMs(sb, totalPartial);
1793                            sb.append("partial");
1794                        }
1795                        if (totalWindow != 0) {
1796                            if (needComma) {
1797                                sb.append(", ");
1798                            }
1799                            needComma = true;
1800                            formatTimeMs(sb, totalWindow);
1801                            sb.append("window");
1802                        }
1803                        sb.append(" realtime");
1804                        pw.println(sb.toString());
1805                    }
1806                }
1807            }
1808
1809            Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
1810            if (sensors.size() > 0) {
1811                for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
1812                    : sensors.entrySet()) {
1813                    Uid.Sensor se = ent.getValue();
1814                    int sensorNumber = ent.getKey();
1815                    sb.setLength(0);
1816                    sb.append(prefix);
1817                    sb.append("    Sensor ");
1818                    int handle = se.getHandle();
1819                    if (handle == Uid.Sensor.GPS) {
1820                        sb.append("GPS");
1821                    } else {
1822                        sb.append(handle);
1823                    }
1824                    sb.append(": ");
1825
1826                    Timer timer = se.getSensorTime();
1827                    if (timer != null) {
1828                        // Convert from microseconds to milliseconds with rounding
1829                        long totalTime = (timer.getTotalTimeLocked(
1830                                batteryRealtime, which) + 500) / 1000;
1831                        int count = timer.getCountLocked(which);
1832                        //timer.logState();
1833                        if (totalTime != 0) {
1834                            formatTimeMs(sb, totalTime);
1835                            sb.append("realtime (");
1836                            sb.append(count);
1837                            sb.append(" times)");
1838                        } else {
1839                            sb.append("(not used)");
1840                        }
1841                    } else {
1842                        sb.append("(not used)");
1843                    }
1844
1845                    pw.println(sb.toString());
1846                    uidActivity = true;
1847                }
1848            }
1849
1850            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
1851            if (processStats.size() > 0) {
1852                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
1853                    : processStats.entrySet()) {
1854                    Uid.Proc ps = ent.getValue();
1855                    long userTime;
1856                    long systemTime;
1857                    int starts;
1858                    int numExcessive;
1859
1860                    userTime = ps.getUserTime(which);
1861                    systemTime = ps.getSystemTime(which);
1862                    starts = ps.getStarts(which);
1863                    numExcessive = which == STATS_SINCE_CHARGED
1864                            ? ps.countExcessivePowers() : 0;
1865
1866                    if (userTime != 0 || systemTime != 0 || starts != 0
1867                            || numExcessive != 0) {
1868                        sb.setLength(0);
1869                        sb.append(prefix); sb.append("    Proc ");
1870                                sb.append(ent.getKey()); sb.append(":\n");
1871                        sb.append(prefix); sb.append("      CPU: ");
1872                                formatTime(sb, userTime); sb.append("usr + ");
1873                                formatTime(sb, systemTime); sb.append("krn");
1874                        if (starts != 0) {
1875                            sb.append("\n"); sb.append(prefix); sb.append("      ");
1876                                    sb.append(starts); sb.append(" proc starts");
1877                        }
1878                        pw.println(sb.toString());
1879                        for (int e=0; e<numExcessive; e++) {
1880                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
1881                            if (ew != null) {
1882                                pw.print(prefix); pw.print("      * Killed for ");
1883                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
1884                                            pw.print("wake lock");
1885                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
1886                                            pw.print("cpu");
1887                                        } else {
1888                                            pw.print("unknown");
1889                                        }
1890                                        pw.print(" use: ");
1891                                        TimeUtils.formatDuration(ew.usedTime, pw);
1892                                        pw.print(" over ");
1893                                        TimeUtils.formatDuration(ew.overTime, pw);
1894                                        pw.print(" (");
1895                                        pw.print((ew.usedTime*100)/ew.overTime);
1896                                        pw.println("%)");
1897                            }
1898                        }
1899                        uidActivity = true;
1900                    }
1901                }
1902            }
1903
1904            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
1905            if (packageStats.size() > 0) {
1906                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
1907                    : packageStats.entrySet()) {
1908                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
1909                    boolean apkActivity = false;
1910                    Uid.Pkg ps = ent.getValue();
1911                    int wakeups = ps.getWakeups(which);
1912                    if (wakeups != 0) {
1913                        pw.print(prefix); pw.print("      ");
1914                                pw.print(wakeups); pw.println(" wakeup alarms");
1915                        apkActivity = true;
1916                    }
1917                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
1918                    if (serviceStats.size() > 0) {
1919                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
1920                                : serviceStats.entrySet()) {
1921                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
1922                            long startTime = ss.getStartTime(batteryUptime, which);
1923                            int starts = ss.getStarts(which);
1924                            int launches = ss.getLaunches(which);
1925                            if (startTime != 0 || starts != 0 || launches != 0) {
1926                                sb.setLength(0);
1927                                sb.append(prefix); sb.append("      Service ");
1928                                        sb.append(sent.getKey()); sb.append(":\n");
1929                                sb.append(prefix); sb.append("        Created for: ");
1930                                        formatTimeMs(sb, startTime / 1000);
1931                                        sb.append(" uptime\n");
1932                                sb.append(prefix); sb.append("        Starts: ");
1933                                        sb.append(starts);
1934                                        sb.append(", launches: "); sb.append(launches);
1935                                pw.println(sb.toString());
1936                                apkActivity = true;
1937                            }
1938                        }
1939                    }
1940                    if (!apkActivity) {
1941                        pw.print(prefix); pw.println("      (nothing executed)");
1942                    }
1943                    uidActivity = true;
1944                }
1945            }
1946            if (!uidActivity) {
1947                pw.print(prefix); pw.println("    (nothing executed)");
1948            }
1949        }
1950    }
1951
1952    static void printBitDescriptions(PrintWriter pw, int oldval, int newval, BitDescription[] descriptions) {
1953        int diff = oldval ^ newval;
1954        if (diff == 0) return;
1955        for (int i=0; i<descriptions.length; i++) {
1956            BitDescription bd = descriptions[i];
1957            if ((diff&bd.mask) != 0) {
1958                if (bd.shift < 0) {
1959                    pw.print((newval&bd.mask) != 0 ? " +" : " -");
1960                    pw.print(bd.name);
1961                } else {
1962                    pw.print(" ");
1963                    pw.print(bd.name);
1964                    pw.print("=");
1965                    int val = (newval&bd.mask)>>bd.shift;
1966                    if (bd.values != null && val >= 0 && val < bd.values.length) {
1967                        pw.print(bd.values[val]);
1968                    } else {
1969                        pw.print(val);
1970                    }
1971                }
1972            }
1973        }
1974    }
1975
1976    public void prepareForDumpLocked() {
1977    }
1978
1979    public static class HistoryPrinter {
1980        int oldState = 0;
1981        int oldStatus = -1;
1982        int oldHealth = -1;
1983        int oldPlug = -1;
1984        int oldTemp = -1;
1985        int oldVolt = -1;
1986
1987        public void printNextItem(PrintWriter pw, HistoryItem rec, long now) {
1988            pw.print("  ");
1989            TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
1990            pw.print(" ");
1991            if (rec.cmd == HistoryItem.CMD_START) {
1992                pw.println(" START");
1993            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
1994                pw.println(" *OVERFLOW*");
1995            } else {
1996                if (rec.batteryLevel < 10) pw.print("00");
1997                else if (rec.batteryLevel < 100) pw.print("0");
1998                pw.print(rec.batteryLevel);
1999                pw.print(" ");
2000                if (rec.states < 0x10) pw.print("0000000");
2001                else if (rec.states < 0x100) pw.print("000000");
2002                else if (rec.states < 0x1000) pw.print("00000");
2003                else if (rec.states < 0x10000) pw.print("0000");
2004                else if (rec.states < 0x100000) pw.print("000");
2005                else if (rec.states < 0x1000000) pw.print("00");
2006                else if (rec.states < 0x10000000) pw.print("0");
2007                pw.print(Integer.toHexString(rec.states));
2008                if (oldStatus != rec.batteryStatus) {
2009                    oldStatus = rec.batteryStatus;
2010                    pw.print(" status=");
2011                    switch (oldStatus) {
2012                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
2013                            pw.print("unknown");
2014                            break;
2015                        case BatteryManager.BATTERY_STATUS_CHARGING:
2016                            pw.print("charging");
2017                            break;
2018                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
2019                            pw.print("discharging");
2020                            break;
2021                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
2022                            pw.print("not-charging");
2023                            break;
2024                        case BatteryManager.BATTERY_STATUS_FULL:
2025                            pw.print("full");
2026                            break;
2027                        default:
2028                            pw.print(oldStatus);
2029                            break;
2030                    }
2031                }
2032                if (oldHealth != rec.batteryHealth) {
2033                    oldHealth = rec.batteryHealth;
2034                    pw.print(" health=");
2035                    switch (oldHealth) {
2036                        case BatteryManager.BATTERY_HEALTH_UNKNOWN:
2037                            pw.print("unknown");
2038                            break;
2039                        case BatteryManager.BATTERY_HEALTH_GOOD:
2040                            pw.print("good");
2041                            break;
2042                        case BatteryManager.BATTERY_HEALTH_OVERHEAT:
2043                            pw.print("overheat");
2044                            break;
2045                        case BatteryManager.BATTERY_HEALTH_DEAD:
2046                            pw.print("dead");
2047                            break;
2048                        case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
2049                            pw.print("over-voltage");
2050                            break;
2051                        case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
2052                            pw.print("failure");
2053                            break;
2054                        default:
2055                            pw.print(oldHealth);
2056                            break;
2057                    }
2058                }
2059                if (oldPlug != rec.batteryPlugType) {
2060                    oldPlug = rec.batteryPlugType;
2061                    pw.print(" plug=");
2062                    switch (oldPlug) {
2063                        case 0:
2064                            pw.print("none");
2065                            break;
2066                        case BatteryManager.BATTERY_PLUGGED_AC:
2067                            pw.print("ac");
2068                            break;
2069                        case BatteryManager.BATTERY_PLUGGED_USB:
2070                            pw.print("usb");
2071                            break;
2072                        default:
2073                            pw.print(oldPlug);
2074                            break;
2075                    }
2076                }
2077                if (oldTemp != rec.batteryTemperature) {
2078                    oldTemp = rec.batteryTemperature;
2079                    pw.print(" temp=");
2080                    pw.print(oldTemp);
2081                }
2082                if (oldVolt != rec.batteryVoltage) {
2083                    oldVolt = rec.batteryVoltage;
2084                    pw.print(" volt=");
2085                    pw.print(oldVolt);
2086                }
2087                printBitDescriptions(pw, oldState, rec.states,
2088                        HISTORY_STATE_DESCRIPTIONS);
2089                pw.println();
2090            }
2091            oldState = rec.states;
2092        }
2093    }
2094
2095    /**
2096     * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
2097     *
2098     * @param pw a Printer to receive the dump output.
2099     */
2100    @SuppressWarnings("unused")
2101    public void dumpLocked(PrintWriter pw) {
2102        prepareForDumpLocked();
2103
2104        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
2105
2106        final HistoryItem rec = new HistoryItem();
2107        if (startIteratingHistoryLocked()) {
2108            pw.println("Battery History:");
2109            HistoryPrinter hprinter = new HistoryPrinter();
2110            while (getNextHistoryLocked(rec)) {
2111                hprinter.printNextItem(pw, rec, now);
2112            }
2113            finishIteratingHistoryLocked();
2114            pw.println("");
2115        }
2116
2117        if (startIteratingOldHistoryLocked()) {
2118            pw.println("Old battery History:");
2119            HistoryPrinter hprinter = new HistoryPrinter();
2120            while (getNextOldHistoryLocked(rec)) {
2121                hprinter.printNextItem(pw, rec, now);
2122            }
2123            finishIteratingOldHistoryLocked();
2124            pw.println("");
2125        }
2126
2127        SparseArray<? extends Uid> uidStats = getUidStats();
2128        final int NU = uidStats.size();
2129        boolean didPid = false;
2130        long nowRealtime = SystemClock.elapsedRealtime();
2131        for (int i=0; i<NU; i++) {
2132            Uid uid = uidStats.valueAt(i);
2133            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
2134            if (pids != null) {
2135                for (int j=0; j<pids.size(); j++) {
2136                    Uid.Pid pid = pids.valueAt(j);
2137                    if (!didPid) {
2138                        pw.println("Per-PID Stats:");
2139                        didPid = true;
2140                    }
2141                    long time = pid.mWakeSum + (pid.mWakeStart != 0
2142                            ? (nowRealtime - pid.mWakeStart) : 0);
2143                    pw.print("  PID "); pw.print(pids.keyAt(j));
2144                            pw.print(" wake time: ");
2145                            TimeUtils.formatDuration(time, pw);
2146                            pw.println("");
2147                }
2148            }
2149        }
2150        if (didPid) {
2151            pw.println("");
2152        }
2153
2154        pw.println("Statistics since last charge:");
2155        pw.println("  System starts: " + getStartCount()
2156                + ", currently on battery: " + getIsOnBattery());
2157        dumpLocked(pw, "", STATS_SINCE_CHARGED, -1);
2158        pw.println("");
2159        pw.println("Statistics since last unplugged:");
2160        dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, -1);
2161    }
2162
2163    @SuppressWarnings("unused")
2164    public void dumpCheckinLocked(PrintWriter pw, String[] args, List<ApplicationInfo> apps) {
2165        prepareForDumpLocked();
2166
2167        boolean isUnpluggedOnly = false;
2168
2169        for (String arg : args) {
2170            if ("-u".equals(arg)) {
2171                if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
2172                isUnpluggedOnly = true;
2173            }
2174        }
2175
2176        if (apps != null) {
2177            SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
2178            for (int i=0; i<apps.size(); i++) {
2179                ApplicationInfo ai = apps.get(i);
2180                ArrayList<String> pkgs = uids.get(ai.uid);
2181                if (pkgs == null) {
2182                    pkgs = new ArrayList<String>();
2183                    uids.put(ai.uid, pkgs);
2184                }
2185                pkgs.add(ai.packageName);
2186            }
2187            SparseArray<? extends Uid> uidStats = getUidStats();
2188            final int NU = uidStats.size();
2189            String[] lineArgs = new String[2];
2190            for (int i=0; i<NU; i++) {
2191                int uid = uidStats.keyAt(i);
2192                ArrayList<String> pkgs = uids.get(uid);
2193                if (pkgs != null) {
2194                    for (int j=0; j<pkgs.size(); j++) {
2195                        lineArgs[0] = Integer.toString(uid);
2196                        lineArgs[1] = pkgs.get(j);
2197                        dumpLine(pw, 0 /* uid */, "i" /* category */, UID_DATA,
2198                                (Object[])lineArgs);
2199                    }
2200                }
2201            }
2202        }
2203        if (isUnpluggedOnly) {
2204            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2205        }
2206        else {
2207            dumpCheckinLocked(pw, STATS_SINCE_CHARGED, -1);
2208            dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
2209        }
2210    }
2211}
2212