OSDN Git Service

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