• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2007 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 com.android.internal.os;
18 
19 import android.bluetooth.BluetoothHeadset;
20 import android.os.BatteryStats;
21 import android.os.NetStat;
22 import android.os.Parcel;
23 import android.os.ParcelFormatException;
24 import android.os.Parcelable;
25 import android.os.Process;
26 import android.os.SystemClock;
27 import android.telephony.ServiceState;
28 import android.telephony.SignalStrength;
29 import android.telephony.TelephonyManager;
30 import android.util.Log;
31 import android.util.PrintWriterPrinter;
32 import android.util.Printer;
33 import android.util.SparseArray;
34 
35 import java.io.BufferedReader;
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.FileOutputStream;
39 import java.io.FileReader;
40 import java.io.IOException;
41 import java.io.PrintWriter;
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.Iterator;
45 import java.util.Map;
46 
47 /**
48  * All information we are collecting about things that can happen that impact
49  * battery life.  All times are represented in microseconds except where indicated
50  * otherwise.
51  */
52 public final class BatteryStatsImpl extends BatteryStats {
53     private static final String TAG = "BatteryStatsImpl";
54     private static final boolean DEBUG = false;
55 
56     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
57     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
58 
59     // Current on-disk Parcel version
60     private static final int VERSION = 41;
61 
62     private static int sNumSpeedSteps;
63 
64     private final File mFile;
65     private final File mBackupFile;
66 
67     /**
68      * The statistics we have collected organized by uids.
69      */
70     final SparseArray<BatteryStatsImpl.Uid> mUidStats =
71         new SparseArray<BatteryStatsImpl.Uid>();
72 
73     // A set of pools of currently active timers.  When a timer is queried, we will divide the
74     // elapsed time by the number of active timers to arrive at that timer's share of the time.
75     // In order to do this, we must refresh each timer whenever the number of active timers
76     // changes.
77     final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>();
78     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>();
79     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
80     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
81             = new SparseArray<ArrayList<StopwatchTimer>>();
82 
83     // These are the objects that will want to do something when the device
84     // is unplugged from power.
85     final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
86 
87     int mStartCount;
88 
89     long mBatteryUptime;
90     long mBatteryLastUptime;
91     long mBatteryRealtime;
92     long mBatteryLastRealtime;
93 
94     long mUptime;
95     long mUptimeStart;
96     long mLastUptime;
97     long mRealtime;
98     long mRealtimeStart;
99     long mLastRealtime;
100 
101     boolean mScreenOn;
102     StopwatchTimer mScreenOnTimer;
103 
104     int mScreenBrightnessBin = -1;
105     final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
106 
107     Counter mInputEventCounter;
108 
109     boolean mPhoneOn;
110     StopwatchTimer mPhoneOnTimer;
111 
112     boolean mAudioOn;
113     StopwatchTimer mAudioOnTimer;
114 
115     boolean mVideoOn;
116     StopwatchTimer mVideoOnTimer;
117 
118     int mPhoneSignalStrengthBin = -1;
119     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
120             new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS];
121 
122     StopwatchTimer mPhoneSignalScanningTimer;
123 
124     int mPhoneDataConnectionType = -1;
125     final StopwatchTimer[] mPhoneDataConnectionsTimer =
126             new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
127 
128     boolean mWifiOn;
129     StopwatchTimer mWifiOnTimer;
130     int mWifiOnUid = -1;
131 
132     boolean mWifiRunning;
133     StopwatchTimer mWifiRunningTimer;
134 
135     boolean mBluetoothOn;
136     StopwatchTimer mBluetoothOnTimer;
137 
138     /** Bluetooth headset object */
139     BluetoothHeadset mBtHeadset;
140 
141     /**
142      * These provide time bases that discount the time the device is plugged
143      * in to power.
144      */
145     boolean mOnBattery;
146     boolean mOnBatteryInternal;
147     long mTrackBatteryPastUptime;
148     long mTrackBatteryUptimeStart;
149     long mTrackBatteryPastRealtime;
150     long mTrackBatteryRealtimeStart;
151 
152     long mUnpluggedBatteryUptime;
153     long mUnpluggedBatteryRealtime;
154 
155     /*
156      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
157      */
158     int mDischargeStartLevel;
159     int mDischargeCurrentLevel;
160 
161     long mLastWriteTime = 0; // Milliseconds
162 
163     // Mobile data transferred while on battery
164     private long[] mMobileDataTx = new long[4];
165     private long[] mMobileDataRx = new long[4];
166     private long[] mTotalDataTx = new long[4];
167     private long[] mTotalDataRx = new long[4];
168 
169     private long mRadioDataUptime;
170     private long mRadioDataStart;
171 
172     private int mBluetoothPingCount;
173     private int mBluetoothPingStart = -1;
174 
175     private int mPhoneServiceState = -1;
176 
177     /*
178      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
179      */
180     private final HashMap<String, SamplingTimer> mKernelWakelockStats =
181             new HashMap<String, SamplingTimer>();
182 
getKernelWakelockStats()183     public Map<String, ? extends SamplingTimer> getKernelWakelockStats() {
184         return mKernelWakelockStats;
185     }
186 
187     private static int sKernelWakelockUpdateVersion = 0;
188 
189     private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
190         Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
191         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
192         Process.PROC_TAB_TERM,
193         Process.PROC_TAB_TERM,
194         Process.PROC_TAB_TERM,
195         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
196     };
197 
198     private final String[] mProcWakelocksName = new String[3];
199     private final long[] mProcWakelocksData = new long[3];
200 
201     /*
202      * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
203      * to mKernelWakelockStats.
204      */
205     private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
206             new HashMap<String, KernelWakelockStats>();
207 
208     private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
209 
210     // For debugging
BatteryStatsImpl()211     public BatteryStatsImpl() {
212         mFile = mBackupFile = null;
213     }
214 
215     public static interface Unpluggable {
unplug(long batteryUptime, long batteryRealtime)216         void unplug(long batteryUptime, long batteryRealtime);
plug(long batteryUptime, long batteryRealtime)217         void plug(long batteryUptime, long batteryRealtime);
218     }
219 
220     /**
221      * State for keeping track of counting information.
222      */
223     public static class Counter extends BatteryStats.Counter implements Unpluggable {
224         int mCount;
225         int mLoadedCount;
226         int mLastCount;
227         int mUnpluggedCount;
228         int mPluggedCount;
229 
Counter(ArrayList<Unpluggable> unpluggables, Parcel in)230         Counter(ArrayList<Unpluggable> unpluggables, Parcel in) {
231             mPluggedCount = mCount = in.readInt();
232             mLoadedCount = in.readInt();
233             mLastCount = in.readInt();
234             mUnpluggedCount = in.readInt();
235             unpluggables.add(this);
236         }
237 
Counter(ArrayList<Unpluggable> unpluggables)238         Counter(ArrayList<Unpluggable> unpluggables) {
239             unpluggables.add(this);
240         }
241 
writeToParcel(Parcel out)242         public void writeToParcel(Parcel out) {
243             out.writeInt(mCount);
244             out.writeInt(mLoadedCount);
245             out.writeInt(mLastCount);
246             out.writeInt(mUnpluggedCount);
247         }
248 
unplug(long batteryUptime, long batteryRealtime)249         public void unplug(long batteryUptime, long batteryRealtime) {
250             mUnpluggedCount = mCount = mPluggedCount;
251         }
252 
plug(long batteryUptime, long batteryRealtime)253         public void plug(long batteryUptime, long batteryRealtime) {
254             mPluggedCount = mCount;
255         }
256 
257         /**
258          * Writes a possibly null Counter to a Parcel.
259          *
260          * @param out the Parcel to be written to.
261          * @param counter a Counter, or null.
262          */
writeCounterToParcel(Parcel out, Counter counter)263         public static void writeCounterToParcel(Parcel out, Counter counter) {
264             if (counter == null) {
265                 out.writeInt(0); // indicates null
266                 return;
267             }
268             out.writeInt(1); // indicates non-null
269 
270             counter.writeToParcel(out);
271         }
272 
273         @Override
getCountLocked(int which)274         public int getCountLocked(int which) {
275             int val;
276             if (which == STATS_LAST) {
277                 val = mLastCount;
278             } else {
279                 val = mCount;
280                 if (which == STATS_UNPLUGGED) {
281                     val -= mUnpluggedCount;
282                 } else if (which != STATS_TOTAL) {
283                     val -= mLoadedCount;
284                 }
285             }
286 
287             return val;
288         }
289 
logState(Printer pw, String prefix)290         public void logState(Printer pw, String prefix) {
291             pw.println(prefix + "mCount=" + mCount
292                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
293                     + " mUnpluggedCount=" + mUnpluggedCount
294                     + " mPluggedCount=" + mPluggedCount);
295         }
296 
stepLocked()297         void stepLocked() {
298             mCount++;
299         }
300 
writeSummaryFromParcelLocked(Parcel out)301         void writeSummaryFromParcelLocked(Parcel out) {
302             out.writeInt(mCount);
303             out.writeInt(mCount - mLoadedCount);
304         }
305 
readSummaryFromParcelLocked(Parcel in)306         void readSummaryFromParcelLocked(Parcel in) {
307             mCount = mLoadedCount = in.readInt();
308             mLastCount = in.readInt();
309             mUnpluggedCount = mPluggedCount = mCount;
310         }
311     }
312 
313     public static class SamplingCounter extends Counter {
314 
SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in)315         SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
316             super(unpluggables, in);
317         }
318 
SamplingCounter(ArrayList<Unpluggable> unpluggables)319         SamplingCounter(ArrayList<Unpluggable> unpluggables) {
320             super(unpluggables);
321         }
322 
addCountLocked(long count)323         public void addCountLocked(long count) {
324             mCount += count;
325         }
326     }
327 
328     /**
329      * State for keeping track of timing information.
330      */
331     public static abstract class Timer extends BatteryStats.Timer implements Unpluggable {
332         final int mType;
333 
334 
335         int mCount;
336         int mLoadedCount;
337         int mLastCount;
338         int mUnpluggedCount;
339 
340         // Times are in microseconds for better accuracy when dividing by the
341         // lock count, and are in "battery realtime" units.
342 
343         /**
344          * The total time we have accumulated since the start of the original
345          * boot, to the last time something interesting happened in the
346          * current run.
347          */
348         long mTotalTime;
349 
350         /**
351          * The total time we loaded for the previous runs.  Subtract this from
352          * mTotalTime to find the time for the current run of the system.
353          */
354         long mLoadedTime;
355 
356         /**
357          * The run time of the last run of the system, as loaded from the
358          * saved data.
359          */
360         long mLastTime;
361 
362         /**
363          * The value of mTotalTime when unplug() was last called.  Subtract
364          * this from mTotalTime to find the time since the last unplug from
365          * power.
366          */
367         long mUnpluggedTime;
368 
369         /**
370          * Constructs from a parcel.
371          * @param type
372          * @param unpluggables
373          * @param powerType
374          * @param in
375          */
Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in)376         Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
377             mType = type;
378 
379             mCount = in.readInt();
380             mLoadedCount = in.readInt();
381             mLastCount = in.readInt();
382             mUnpluggedCount = in.readInt();
383             mTotalTime = in.readLong();
384             mLoadedTime = in.readLong();
385             mLastTime = in.readLong();
386             mUnpluggedTime = in.readLong();
387             unpluggables.add(this);
388         }
389 
Timer(int type, ArrayList<Unpluggable> unpluggables)390         Timer(int type, ArrayList<Unpluggable> unpluggables) {
391             mType = type;
392             unpluggables.add(this);
393         }
394 
computeRunTimeLocked(long curBatteryRealtime)395         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
396 
computeCurrentCountLocked()397         protected abstract int computeCurrentCountLocked();
398 
399 
writeToParcel(Parcel out, long batteryRealtime)400         public void writeToParcel(Parcel out, long batteryRealtime) {
401             out.writeInt(mCount);
402             out.writeInt(mLoadedCount);
403             out.writeInt(mLastCount);
404             out.writeInt(mUnpluggedCount);
405             out.writeLong(computeRunTimeLocked(batteryRealtime));
406             out.writeLong(mLoadedTime);
407             out.writeLong(mLastTime);
408             out.writeLong(mUnpluggedTime);
409         }
410 
unplug(long batteryUptime, long batteryRealtime)411         public void unplug(long batteryUptime, long batteryRealtime) {
412             if (DEBUG && mType < 0) {
413                 Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime
414                         + " old mUnpluggedTime=" + mUnpluggedTime
415                         + " old mUnpluggedCount=" + mUnpluggedCount);
416             }
417             mUnpluggedTime = computeRunTimeLocked(batteryRealtime);
418             mUnpluggedCount = mCount;
419             if (DEBUG && mType < 0) {
420                 Log.v(TAG, "unplug #" + mType
421                         + ": new mUnpluggedTime=" + mUnpluggedTime
422                         + " new mUnpluggedCount=" + mUnpluggedCount);
423             }
424         }
425 
plug(long batteryUptime, long batteryRealtime)426         public void plug(long batteryUptime, long batteryRealtime) {
427             if (DEBUG && mType < 0) {
428                 Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
429                         + " old mTotalTime=" + mTotalTime);
430             }
431             mTotalTime = computeRunTimeLocked(batteryRealtime);
432             mCount = computeCurrentCountLocked();
433             if (DEBUG && mType < 0) {
434                 Log.v(TAG, "plug #" + mType
435                         + ": new mTotalTime=" + mTotalTime);
436             }
437         }
438 
439         /**
440          * Writes a possibly null Timer to a Parcel.
441          *
442          * @param out the Parcel to be written to.
443          * @param timer a Timer, or null.
444          */
writeTimerToParcel(Parcel out, Timer timer, long batteryRealtime)445         public static void writeTimerToParcel(Parcel out, Timer timer,
446                 long batteryRealtime) {
447             if (timer == null) {
448                 out.writeInt(0); // indicates null
449                 return;
450             }
451             out.writeInt(1); // indicates non-null
452 
453             timer.writeToParcel(out, batteryRealtime);
454         }
455 
456         @Override
getTotalTimeLocked(long batteryRealtime, int which)457         public long getTotalTimeLocked(long batteryRealtime, int which) {
458             long val;
459             if (which == STATS_LAST) {
460                 val = mLastTime;
461             } else {
462                 val = computeRunTimeLocked(batteryRealtime);
463                 if (which == STATS_UNPLUGGED) {
464                     val -= mUnpluggedTime;
465                 } else if (which != STATS_TOTAL) {
466                     val -= mLoadedTime;
467                 }
468             }
469 
470             return val;
471         }
472 
473         @Override
getCountLocked(int which)474         public int getCountLocked(int which) {
475             int val;
476             if (which == STATS_LAST) {
477                 val = mLastCount;
478             } else {
479                 val = computeCurrentCountLocked();
480                 if (which == STATS_UNPLUGGED) {
481                     val -= mUnpluggedCount;
482                 } else if (which != STATS_TOTAL) {
483                     val -= mLoadedCount;
484                 }
485             }
486 
487             return val;
488         }
489 
logState(Printer pw, String prefix)490         public void logState(Printer pw, String prefix) {
491             pw.println(prefix + " mCount=" + mCount
492                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
493                     + " mUnpluggedCount=" + mUnpluggedCount);
494             pw.println(prefix + "mTotalTime=" + mTotalTime
495                     + " mLoadedTime=" + mLoadedTime);
496             pw.println(prefix + "mLastTime=" + mLastTime
497                     + " mUnpluggedTime=" + mUnpluggedTime);
498         }
499 
500 
writeSummaryFromParcelLocked(Parcel out, long batteryRealtime)501         void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
502             long runTime = computeRunTimeLocked(batteryRealtime);
503             // Divide by 1000 for backwards compatibility
504             out.writeLong((runTime + 500) / 1000);
505             out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
506             out.writeInt(mCount);
507             out.writeInt(mCount - mLoadedCount);
508         }
509 
readSummaryFromParcelLocked(Parcel in)510         void readSummaryFromParcelLocked(Parcel in) {
511             // Multiply by 1000 for backwards compatibility
512             mTotalTime = mLoadedTime = in.readLong() * 1000;
513             mLastTime = in.readLong() * 1000;
514             mUnpluggedTime = mTotalTime;
515             mCount = mLoadedCount = in.readInt();
516             mLastCount = in.readInt();
517             mUnpluggedCount = mCount;
518         }
519     }
520 
521     public static final class SamplingTimer extends Timer {
522 
523         /**
524          * The most recent reported count from /proc/wakelocks.
525          */
526         int mCurrentReportedCount;
527 
528         /**
529          * The reported count from /proc/wakelocks when unplug() was last
530          * called.
531          */
532         int mUnpluggedReportedCount;
533 
534         /**
535          * The most recent reported total_time from /proc/wakelocks.
536          */
537         long mCurrentReportedTotalTime;
538 
539 
540         /**
541          * The reported total_time from /proc/wakelocks when unplug() was last
542          * called.
543          */
544         long mUnpluggedReportedTotalTime;
545 
546         /**
547          * Whether we are currently in a discharge cycle.
548          */
549         boolean mInDischarge;
550 
551         /**
552          * Whether we are currently recording reported values.
553          */
554         boolean mTrackingReportedValues;
555 
556         /*
557          * A sequnce counter, incremented once for each update of the stats.
558          */
559         int mUpdateVersion;
560 
SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in)561         SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) {
562             super(0, unpluggables, in);
563             mCurrentReportedCount = in.readInt();
564             mUnpluggedReportedCount = in.readInt();
565             mCurrentReportedTotalTime = in.readLong();
566             mUnpluggedReportedTotalTime = in.readLong();
567             mTrackingReportedValues = in.readInt() == 1;
568             mInDischarge = inDischarge;
569         }
570 
SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, boolean trackReportedValues)571         SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
572                 boolean trackReportedValues) {
573             super(0, unpluggables);
574             mTrackingReportedValues = trackReportedValues;
575             mInDischarge = inDischarge;
576         }
577 
setStale()578         public void setStale() {
579             mTrackingReportedValues = false;
580             mUnpluggedReportedTotalTime = 0;
581             mUnpluggedReportedCount = 0;
582         }
583 
setUpdateVersion(int version)584         public void setUpdateVersion(int version) {
585             mUpdateVersion = version;
586         }
587 
getUpdateVersion()588         public int getUpdateVersion() {
589             return mUpdateVersion;
590         }
591 
updateCurrentReportedCount(int count)592         public void updateCurrentReportedCount(int count) {
593             if (mInDischarge && mUnpluggedReportedCount == 0) {
594                 // Updating the reported value for the first time.
595                 mUnpluggedReportedCount = count;
596                 // If we are receiving an update update mTrackingReportedValues;
597                 mTrackingReportedValues = true;
598             }
599             mCurrentReportedCount = count;
600         }
601 
updateCurrentReportedTotalTime(long totalTime)602         public void updateCurrentReportedTotalTime(long totalTime) {
603             if (mInDischarge && mUnpluggedReportedTotalTime == 0) {
604                 // Updating the reported value for the first time.
605                 mUnpluggedReportedTotalTime = totalTime;
606                 // If we are receiving an update update mTrackingReportedValues;
607                 mTrackingReportedValues = true;
608             }
609             mCurrentReportedTotalTime = totalTime;
610         }
611 
unplug(long batteryUptime, long batteryRealtime)612         public void unplug(long batteryUptime, long batteryRealtime) {
613             super.unplug(batteryUptime, batteryRealtime);
614             if (mTrackingReportedValues) {
615                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
616                 mUnpluggedReportedCount = mCurrentReportedCount;
617             }
618             mInDischarge = true;
619         }
620 
plug(long batteryUptime, long batteryRealtime)621         public void plug(long batteryUptime, long batteryRealtime) {
622             super.plug(batteryUptime, batteryRealtime);
623             mInDischarge = false;
624         }
625 
logState(Printer pw, String prefix)626         public void logState(Printer pw, String prefix) {
627             super.logState(pw, prefix);
628             pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
629                     + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
630                     + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
631                     + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
632         }
633 
computeRunTimeLocked(long curBatteryRealtime)634         protected long computeRunTimeLocked(long curBatteryRealtime) {
635             return mTotalTime + (mInDischarge && mTrackingReportedValues
636                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
637         }
638 
computeCurrentCountLocked()639         protected int computeCurrentCountLocked() {
640             return mCount + (mInDischarge && mTrackingReportedValues
641                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
642         }
643 
writeToParcel(Parcel out, long batteryRealtime)644         public void writeToParcel(Parcel out, long batteryRealtime) {
645             super.writeToParcel(out, batteryRealtime);
646             out.writeInt(mCurrentReportedCount);
647             out.writeInt(mUnpluggedReportedCount);
648             out.writeLong(mCurrentReportedTotalTime);
649             out.writeLong(mUnpluggedReportedTotalTime);
650             out.writeInt(mTrackingReportedValues ? 1 : 0);
651         }
652 
writeSummaryFromParcelLocked(Parcel out, long batteryRealtime)653         void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
654             super.writeSummaryFromParcelLocked(out, batteryRealtime);
655             out.writeLong(mCurrentReportedTotalTime);
656             out.writeInt(mCurrentReportedCount);
657             out.writeInt(mTrackingReportedValues ? 1 : 0);
658         }
659 
readSummaryFromParcelLocked(Parcel in)660         void readSummaryFromParcelLocked(Parcel in) {
661             super.readSummaryFromParcelLocked(in);
662             mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
663             mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
664             mTrackingReportedValues = in.readInt() == 1;
665         }
666     }
667 
668     /**
669      * State for keeping track of timing information.
670      */
671     public static final class StopwatchTimer extends Timer {
672         final ArrayList<StopwatchTimer> mTimerPool;
673         int mNesting;
674 
675 
676         /**
677          * The last time at which we updated the timer.  If mNesting is > 0,
678          * subtract this from the current battery time to find the amount of
679          * time we have been running since we last computed an update.
680          */
681         long mUpdateTime;
682 
683         /**
684          * The total time at which the timer was acquired, to determine if
685          * was actually held for an interesting duration.
686          */
687         long mAcquireTime;
688 
689         long mTimeout;
690 
StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, ArrayList<Unpluggable> unpluggables, Parcel in)691         StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
692                 ArrayList<Unpluggable> unpluggables, Parcel in) {
693             super(type, unpluggables, in);
694             mTimerPool = timerPool;
695             mUpdateTime = in.readLong();
696         }
697 
StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, ArrayList<Unpluggable> unpluggables)698         StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
699                 ArrayList<Unpluggable> unpluggables) {
700             super(type, unpluggables);
701             mTimerPool = timerPool;
702         }
703 
setTimeout(long timeout)704         void setTimeout(long timeout) {
705             mTimeout = timeout;
706         }
707 
writeToParcel(Parcel out, long batteryRealtime)708         public void writeToParcel(Parcel out, long batteryRealtime) {
709             super.writeToParcel(out, batteryRealtime);
710             out.writeLong(mUpdateTime);
711         }
712 
plug(long batteryUptime, long batteryRealtime)713         public void plug(long batteryUptime, long batteryRealtime) {
714             if (mNesting > 0) {
715                 if (DEBUG && mType < 0) {
716                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
717                 }
718                 super.plug(batteryUptime, batteryRealtime);
719                 mUpdateTime = batteryRealtime;
720                 if (DEBUG && mType < 0) {
721                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
722                 }
723             }
724         }
725 
logState(Printer pw, String prefix)726         public void logState(Printer pw, String prefix) {
727             super.logState(pw, prefix);
728             pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime
729                     + " mAcquireTime=" + mAcquireTime);
730         }
731 
startRunningLocked(BatteryStatsImpl stats)732         void startRunningLocked(BatteryStatsImpl stats) {
733             if (mNesting++ == 0) {
734                 mUpdateTime = stats.getBatteryRealtimeLocked(
735                         SystemClock.elapsedRealtime() * 1000);
736                 if (mTimerPool != null) {
737                     // Accumulate time to all currently active timers before adding
738                     // this new one to the pool.
739                     refreshTimersLocked(stats, mTimerPool);
740                     // Add this timer to the active pool
741                     mTimerPool.add(this);
742                 }
743                 // Increment the count
744                 mCount++;
745                 mAcquireTime = mTotalTime;
746                 if (DEBUG && mType < 0) {
747                     Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
748                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
749                             + " mAcquireTime=" + mAcquireTime);
750                 }
751             }
752         }
753 
isRunningLocked()754         boolean isRunningLocked() {
755             return mNesting > 0;
756         }
757 
stopRunningLocked(BatteryStatsImpl stats)758         void stopRunningLocked(BatteryStatsImpl stats) {
759             // Ignore attempt to stop a timer that isn't running
760             if (mNesting == 0) {
761                 return;
762             }
763             if (--mNesting == 0) {
764                 if (mTimerPool != null) {
765                     // Accumulate time to all active counters, scaled by the total
766                     // active in the pool, before taking this one out of the pool.
767                     refreshTimersLocked(stats, mTimerPool);
768                     // Remove this timer from the active pool
769                     mTimerPool.remove(this);
770                 } else {
771                     final long realtime = SystemClock.elapsedRealtime() * 1000;
772                     final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
773                     mNesting = 1;
774                     mTotalTime = computeRunTimeLocked(batteryRealtime);
775                     mNesting = 0;
776                 }
777 
778                 if (DEBUG && mType < 0) {
779                     Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
780                             + " mTotalTime=" + mTotalTime + " mCount=" + mCount
781                             + " mAcquireTime=" + mAcquireTime);
782                 }
783 
784                 if (mTotalTime == mAcquireTime) {
785                     // If there was no change in the time, then discard this
786                     // count.  A somewhat cheezy strategy, but hey.
787                     mCount--;
788                 }
789             }
790         }
791 
792         // Update the total time for all other running Timers with the same type as this Timer
793         // due to a change in timer count
refreshTimersLocked(final BatteryStatsImpl stats, final ArrayList<StopwatchTimer> pool)794         private static void refreshTimersLocked(final BatteryStatsImpl stats,
795                 final ArrayList<StopwatchTimer> pool) {
796             final long realtime = SystemClock.elapsedRealtime() * 1000;
797             final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
798             final int N = pool.size();
799             for (int i=N-1; i>= 0; i--) {
800                 final StopwatchTimer t = pool.get(i);
801                 long heldTime = batteryRealtime - t.mUpdateTime;
802                 if (heldTime > 0) {
803                     t.mTotalTime += heldTime / N;
804                 }
805                 t.mUpdateTime = batteryRealtime;
806             }
807         }
808 
809         @Override
computeRunTimeLocked(long curBatteryRealtime)810         protected long computeRunTimeLocked(long curBatteryRealtime) {
811             if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
812                 curBatteryRealtime = mUpdateTime + mTimeout;
813             }
814             return mTotalTime + (mNesting > 0
815                     ? (curBatteryRealtime - mUpdateTime)
816                             / (mTimerPool != null ? mTimerPool.size() : 1)
817                     : 0);
818         }
819 
820         @Override
computeCurrentCountLocked()821         protected int computeCurrentCountLocked() {
822             return mCount;
823         }
824 
readSummaryFromParcelLocked(Parcel in)825         void readSummaryFromParcelLocked(Parcel in) {
826             super.readSummaryFromParcelLocked(in);
827             mNesting = 0;
828         }
829     }
830 
readKernelWakelockStats()831     private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
832 
833         byte[] buffer = new byte[4096];
834         int len;
835 
836         try {
837             FileInputStream is = new FileInputStream("/proc/wakelocks");
838             len = is.read(buffer);
839             is.close();
840 
841             if (len > 0) {
842                 int i;
843                 for (i=0; i<len; i++) {
844                     if (buffer[i] == '\0') {
845                         len = i;
846                         break;
847                     }
848                 }
849             }
850         } catch (java.io.FileNotFoundException e) {
851             return null;
852         } catch (java.io.IOException e) {
853             return null;
854         }
855 
856         return parseProcWakelocks(buffer, len);
857     }
858 
parseProcWakelocks( byte[] wlBuffer, int len)859     private final Map<String, KernelWakelockStats> parseProcWakelocks(
860             byte[] wlBuffer, int len) {
861         String name;
862         int count;
863         long totalTime;
864         int startIndex, endIndex;
865         int numUpdatedWlNames = 0;
866 
867         // Advance past the first line.
868         int i;
869         for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
870         startIndex = endIndex = i + 1;
871 
872         synchronized(this) {
873             Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
874 
875             sKernelWakelockUpdateVersion++;
876             while (endIndex < len) {
877                 for (endIndex=startIndex;
878                         endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
879                         endIndex++);
880                 endIndex++; // endIndex is an exclusive upper bound.
881 
882                 String[] nameStringArray = mProcWakelocksName;
883                 long[] wlData = mProcWakelocksData;
884                 boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
885                         PROC_WAKELOCKS_FORMAT, nameStringArray, wlData, null);
886 
887                 name = nameStringArray[0];
888                 count = (int) wlData[1];
889                 // convert nanoseconds to microseconds with rounding.
890                 totalTime = (wlData[2] + 500) / 1000;
891 
892                 if (parsed && name.length() > 0) {
893                     if (!m.containsKey(name)) {
894                         m.put(name, new KernelWakelockStats(count, totalTime,
895                                 sKernelWakelockUpdateVersion));
896                         numUpdatedWlNames++;
897                     } else {
898                         KernelWakelockStats kwlStats = m.get(name);
899                         if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
900                             kwlStats.mCount += count;
901                             kwlStats.mTotalTime += totalTime;
902                         } else {
903                             kwlStats.mCount = count;
904                             kwlStats.mTotalTime = totalTime;
905                             kwlStats.mVersion = sKernelWakelockUpdateVersion;
906                             numUpdatedWlNames++;
907                         }
908                     }
909                 }
910                 startIndex = endIndex;
911             }
912 
913             if (m.size() != numUpdatedWlNames) {
914                 // Don't report old data.
915                 Iterator<KernelWakelockStats> itr = m.values().iterator();
916                 while (itr.hasNext()) {
917                     if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
918                         itr.remove();
919                     }
920                 }
921             }
922             return m;
923         }
924     }
925 
926     private class KernelWakelockStats {
927         public int mCount;
928         public long mTotalTime;
929         public int mVersion;
930 
KernelWakelockStats(int count, long totalTime, int version)931         KernelWakelockStats(int count, long totalTime, int version) {
932             mCount = count;
933             mTotalTime = totalTime;
934             mVersion = version;
935         }
936     }
937 
938     /*
939      * Get the KernelWakelockTimer associated with name, and create a new one if one
940      * doesn't already exist.
941      */
getKernelWakelockTimerLocked(String name)942     public SamplingTimer getKernelWakelockTimerLocked(String name) {
943         SamplingTimer kwlt = mKernelWakelockStats.get(name);
944         if (kwlt == null) {
945             kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
946                     true /* track reported values */);
947             mKernelWakelockStats.put(name, kwlt);
948         }
949         return kwlt;
950     }
951 
doDataPlug(long[] dataTransfer, long currentBytes)952     private void doDataPlug(long[] dataTransfer, long currentBytes) {
953         dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED];
954         dataTransfer[STATS_UNPLUGGED] = -1;
955     }
956 
doDataUnplug(long[] dataTransfer, long currentBytes)957     private void doDataUnplug(long[] dataTransfer, long currentBytes) {
958         dataTransfer[STATS_UNPLUGGED] = currentBytes;
959     }
960 
961     /**
962      * Radio uptime in microseconds when transferring data. This value is very approximate.
963      * @return
964      */
getCurrentRadioDataUptime()965     private long getCurrentRadioDataUptime() {
966         try {
967             File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms");
968             if (!awakeTimeFile.exists()) return 0;
969             BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile));
970             String line = br.readLine();
971             br.close();
972             return Long.parseLong(line) * 1000;
973         } catch (NumberFormatException nfe) {
974             // Nothing
975         } catch (IOException ioe) {
976             // Nothing
977         }
978         return 0;
979     }
980 
981     /**
982      * @deprecated use getRadioDataUptime
983      */
getRadioDataUptimeMs()984     public long getRadioDataUptimeMs() {
985         return getRadioDataUptime() / 1000;
986     }
987 
988     /**
989      * Returns the duration that the cell radio was up for data transfers.
990      */
getRadioDataUptime()991     public long getRadioDataUptime() {
992         if (mRadioDataStart == -1) {
993             return mRadioDataUptime;
994         } else {
995             return getCurrentRadioDataUptime() - mRadioDataStart;
996         }
997     }
998 
getCurrentBluetoothPingCount()999     private int getCurrentBluetoothPingCount() {
1000         if (mBtHeadset != null) {
1001             return mBtHeadset.getBatteryUsageHint();
1002         }
1003         return -1;
1004     }
1005 
getBluetoothPingCount()1006     public int getBluetoothPingCount() {
1007         if (mBluetoothPingStart == -1) {
1008             return mBluetoothPingCount;
1009         } else if (mBtHeadset != null) {
1010             return getCurrentBluetoothPingCount() - mBluetoothPingStart;
1011         }
1012         return 0;
1013     }
1014 
setBtHeadset(BluetoothHeadset headset)1015     public void setBtHeadset(BluetoothHeadset headset) {
1016         if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) {
1017             mBluetoothPingStart = getCurrentBluetoothPingCount();
1018         }
1019         mBtHeadset = headset;
1020     }
1021 
doUnplug(long batteryUptime, long batteryRealtime)1022     public void doUnplug(long batteryUptime, long batteryRealtime) {
1023         for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
1024             Uid u = mUidStats.valueAt(iu);
1025             u.mStartedTcpBytesReceived = NetStat.getUidRxBytes(u.mUid);
1026             u.mStartedTcpBytesSent = NetStat.getUidTxBytes(u.mUid);
1027             u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
1028             u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
1029         }
1030         for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
1031             mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
1032         }
1033         // Track total mobile data
1034         doDataUnplug(mMobileDataRx, NetStat.getMobileRxBytes());
1035         doDataUnplug(mMobileDataTx, NetStat.getMobileTxBytes());
1036         doDataUnplug(mTotalDataRx, NetStat.getTotalRxBytes());
1037         doDataUnplug(mTotalDataTx, NetStat.getTotalTxBytes());
1038         // Track radio awake time
1039         mRadioDataStart = getCurrentRadioDataUptime();
1040         mRadioDataUptime = 0;
1041         // Track bt headset ping count
1042         mBluetoothPingStart = getCurrentBluetoothPingCount();
1043         mBluetoothPingCount = 0;
1044     }
1045 
doPlug(long batteryUptime, long batteryRealtime)1046     public void doPlug(long batteryUptime, long batteryRealtime) {
1047         for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
1048             Uid u = mUidStats.valueAt(iu);
1049             if (u.mStartedTcpBytesReceived >= 0) {
1050                 u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
1051                 u.mStartedTcpBytesReceived = -1;
1052             }
1053             if (u.mStartedTcpBytesSent >= 0) {
1054                 u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
1055                 u.mStartedTcpBytesSent = -1;
1056             }
1057         }
1058         for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
1059             mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
1060         }
1061         doDataPlug(mMobileDataRx, NetStat.getMobileRxBytes());
1062         doDataPlug(mMobileDataTx, NetStat.getMobileTxBytes());
1063         doDataPlug(mTotalDataRx, NetStat.getTotalRxBytes());
1064         doDataPlug(mTotalDataTx, NetStat.getTotalTxBytes());
1065         // Track radio awake time
1066         mRadioDataUptime = getRadioDataUptime();
1067         mRadioDataStart = -1;
1068 
1069         // Track bt headset ping count
1070         mBluetoothPingCount = getBluetoothPingCount();
1071         mBluetoothPingStart = -1;
1072     }
1073 
noteStartGps(int uid)1074     public void noteStartGps(int uid) {
1075         getUidStatsLocked(uid).noteStartGps();
1076     }
1077 
noteStopGps(int uid)1078     public void noteStopGps(int uid) {
1079         getUidStatsLocked(uid).noteStopGps();
1080     }
1081 
noteScreenOnLocked()1082     public void noteScreenOnLocked() {
1083         if (!mScreenOn) {
1084             mScreenOn = true;
1085             mScreenOnTimer.startRunningLocked(this);
1086             if (mScreenBrightnessBin >= 0) {
1087                 mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this);
1088             }
1089         }
1090     }
1091 
noteScreenOffLocked()1092     public void noteScreenOffLocked() {
1093         if (mScreenOn) {
1094             mScreenOn = false;
1095             mScreenOnTimer.stopRunningLocked(this);
1096             if (mScreenBrightnessBin >= 0) {
1097                 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
1098             }
1099         }
1100     }
1101 
noteScreenBrightnessLocked(int brightness)1102     public void noteScreenBrightnessLocked(int brightness) {
1103         // Bin the brightness.
1104         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
1105         if (bin < 0) bin = 0;
1106         else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
1107         if (mScreenBrightnessBin != bin) {
1108             if (mScreenOn) {
1109                 if (mScreenBrightnessBin >= 0) {
1110                     mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
1111                 }
1112                 mScreenBrightnessTimer[bin].startRunningLocked(this);
1113             }
1114             mScreenBrightnessBin = bin;
1115         }
1116     }
1117 
noteInputEventLocked()1118     public void noteInputEventLocked() {
1119         mInputEventCounter.stepLocked();
1120     }
1121 
noteUserActivityLocked(int uid, int event)1122     public void noteUserActivityLocked(int uid, int event) {
1123         getUidStatsLocked(uid).noteUserActivityLocked(event);
1124     }
1125 
notePhoneOnLocked()1126     public void notePhoneOnLocked() {
1127         if (!mPhoneOn) {
1128             mPhoneOn = true;
1129             mPhoneOnTimer.startRunningLocked(this);
1130         }
1131     }
1132 
notePhoneOffLocked()1133     public void notePhoneOffLocked() {
1134         if (mPhoneOn) {
1135             mPhoneOn = false;
1136             mPhoneOnTimer.stopRunningLocked(this);
1137         }
1138     }
1139 
1140     /**
1141      * Telephony stack updates the phone state.
1142      * @param state phone state from ServiceState.getState()
1143      */
notePhoneStateLocked(int state)1144     public void notePhoneStateLocked(int state) {
1145         int bin = mPhoneSignalStrengthBin;
1146         boolean isAirplaneMode = state == ServiceState.STATE_POWER_OFF;
1147         // Stop all timers
1148         if (isAirplaneMode || state == ServiceState.STATE_OUT_OF_SERVICE) {
1149             for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) {
1150                 while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
1151                     mPhoneSignalStrengthsTimer[i].stopRunningLocked(this);
1152                 }
1153             }
1154         }
1155         // Stop Signal Scanning timer, in case we're going into service
1156         while (mPhoneSignalScanningTimer.isRunningLocked()) {
1157             mPhoneSignalScanningTimer.stopRunningLocked(this);
1158         }
1159 
1160         // If we're back in service or continuing in service, restart the old timer.
1161         if (state == ServiceState.STATE_IN_SERVICE) {
1162             if (bin == -1) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1163             if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) {
1164                 mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
1165             }
1166         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
1167             mPhoneSignalStrengthBin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1168             if (!mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].isRunningLocked()) {
1169                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].startRunningLocked(this);
1170             }
1171             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
1172                 mPhoneSignalScanningTimer.startRunningLocked(this);
1173             }
1174         }
1175         mPhoneServiceState = state;
1176     }
1177 
notePhoneSignalStrengthLocked(SignalStrength signalStrength)1178     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
1179         // Bin the strength.
1180         int bin;
1181         if (mPhoneServiceState == ServiceState.STATE_POWER_OFF
1182                 || mPhoneServiceState == ServiceState.STATE_OUT_OF_SERVICE) {
1183             // Ignore any signal strength changes when radio was turned off or out of service.
1184             return;
1185         }
1186         if (!signalStrength.isGsm()) {
1187             int dBm = signalStrength.getCdmaDbm();
1188             if (dBm >= -75) bin = SIGNAL_STRENGTH_GREAT;
1189             else if (dBm >= -85) bin = SIGNAL_STRENGTH_GOOD;
1190             else if (dBm >= -95)  bin = SIGNAL_STRENGTH_MODERATE;
1191             else if (dBm >= -100)  bin = SIGNAL_STRENGTH_POOR;
1192             else bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1193         } else {
1194             int asu = signalStrength.getGsmSignalStrength();
1195             if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
1196             else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT;
1197             else if (asu >= 8)  bin = SIGNAL_STRENGTH_GOOD;
1198             else if (asu >= 4)  bin = SIGNAL_STRENGTH_MODERATE;
1199             else bin = SIGNAL_STRENGTH_POOR;
1200         }
1201         if (mPhoneSignalStrengthBin != bin) {
1202             if (mPhoneSignalStrengthBin >= 0) {
1203                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this);
1204             }
1205             mPhoneSignalStrengthBin = bin;
1206             mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
1207         }
1208     }
1209 
notePhoneDataConnectionStateLocked(int dataType, boolean hasData)1210     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
1211         int bin = DATA_CONNECTION_NONE;
1212         if (hasData) {
1213             switch (dataType) {
1214                 case TelephonyManager.NETWORK_TYPE_EDGE:
1215                     bin = DATA_CONNECTION_EDGE;
1216                     break;
1217                 case TelephonyManager.NETWORK_TYPE_GPRS:
1218                     bin = DATA_CONNECTION_GPRS;
1219                     break;
1220                 case TelephonyManager.NETWORK_TYPE_UMTS:
1221                     bin = DATA_CONNECTION_UMTS;
1222                     break;
1223                 default:
1224                     bin = DATA_CONNECTION_OTHER;
1225                     break;
1226             }
1227         }
1228         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
1229         if (mPhoneDataConnectionType != bin) {
1230             if (mPhoneDataConnectionType >= 0) {
1231                 mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this);
1232             }
1233             mPhoneDataConnectionType = bin;
1234             mPhoneDataConnectionsTimer[bin].startRunningLocked(this);
1235         }
1236     }
1237 
noteWifiOnLocked(int uid)1238     public void noteWifiOnLocked(int uid) {
1239         if (!mWifiOn) {
1240             mWifiOn = true;
1241             mWifiOnTimer.startRunningLocked(this);
1242         }
1243         if (mWifiOnUid != uid) {
1244             if (mWifiOnUid >= 0) {
1245                 getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
1246             }
1247             mWifiOnUid = uid;
1248             getUidStatsLocked(uid).noteWifiTurnedOnLocked();
1249         }
1250     }
1251 
noteWifiOffLocked(int uid)1252     public void noteWifiOffLocked(int uid) {
1253         if (mWifiOn) {
1254             mWifiOn = false;
1255             mWifiOnTimer.stopRunningLocked(this);
1256         }
1257         if (mWifiOnUid >= 0) {
1258             getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
1259             mWifiOnUid = -1;
1260         }
1261     }
1262 
noteAudioOnLocked(int uid)1263     public void noteAudioOnLocked(int uid) {
1264         if (!mAudioOn) {
1265             mAudioOn = true;
1266             mAudioOnTimer.startRunningLocked(this);
1267         }
1268         getUidStatsLocked(uid).noteAudioTurnedOnLocked();
1269     }
1270 
noteAudioOffLocked(int uid)1271     public void noteAudioOffLocked(int uid) {
1272         if (mAudioOn) {
1273             mAudioOn = false;
1274             mAudioOnTimer.stopRunningLocked(this);
1275         }
1276         getUidStatsLocked(uid).noteAudioTurnedOffLocked();
1277     }
1278 
noteVideoOnLocked(int uid)1279     public void noteVideoOnLocked(int uid) {
1280         if (!mVideoOn) {
1281             mVideoOn = true;
1282             mVideoOnTimer.startRunningLocked(this);
1283         }
1284         getUidStatsLocked(uid).noteVideoTurnedOnLocked();
1285     }
1286 
noteVideoOffLocked(int uid)1287     public void noteVideoOffLocked(int uid) {
1288         if (mVideoOn) {
1289             mVideoOn = false;
1290             mVideoOnTimer.stopRunningLocked(this);
1291         }
1292         getUidStatsLocked(uid).noteVideoTurnedOffLocked();
1293     }
1294 
noteWifiRunningLocked()1295     public void noteWifiRunningLocked() {
1296         if (!mWifiRunning) {
1297             mWifiRunning = true;
1298             mWifiRunningTimer.startRunningLocked(this);
1299         }
1300     }
1301 
noteWifiStoppedLocked()1302     public void noteWifiStoppedLocked() {
1303         if (mWifiRunning) {
1304             mWifiRunning = false;
1305             mWifiRunningTimer.stopRunningLocked(this);
1306         }
1307     }
1308 
noteBluetoothOnLocked()1309     public void noteBluetoothOnLocked() {
1310         if (!mBluetoothOn) {
1311             mBluetoothOn = true;
1312             mBluetoothOnTimer.startRunningLocked(this);
1313         }
1314     }
1315 
noteBluetoothOffLocked()1316     public void noteBluetoothOffLocked() {
1317         if (mBluetoothOn) {
1318             mBluetoothOn = false;
1319             mBluetoothOnTimer.stopRunningLocked(this);
1320         }
1321     }
1322 
noteFullWifiLockAcquiredLocked(int uid)1323     public void noteFullWifiLockAcquiredLocked(int uid) {
1324         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked();
1325     }
1326 
noteFullWifiLockReleasedLocked(int uid)1327     public void noteFullWifiLockReleasedLocked(int uid) {
1328         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
1329     }
1330 
noteScanWifiLockAcquiredLocked(int uid)1331     public void noteScanWifiLockAcquiredLocked(int uid) {
1332         getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
1333     }
1334 
noteScanWifiLockReleasedLocked(int uid)1335     public void noteScanWifiLockReleasedLocked(int uid) {
1336         getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
1337     }
1338 
noteWifiMulticastEnabledLocked(int uid)1339     public void noteWifiMulticastEnabledLocked(int uid) {
1340         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked();
1341     }
1342 
noteWifiMulticastDisabledLocked(int uid)1343     public void noteWifiMulticastDisabledLocked(int uid) {
1344         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked();
1345     }
1346 
getScreenOnTime(long batteryRealtime, int which)1347     @Override public long getScreenOnTime(long batteryRealtime, int which) {
1348         return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
1349     }
1350 
getScreenBrightnessTime(int brightnessBin, long batteryRealtime, int which)1351     @Override public long getScreenBrightnessTime(int brightnessBin,
1352             long batteryRealtime, int which) {
1353         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
1354                 batteryRealtime, which);
1355     }
1356 
getInputEventCount(int which)1357     @Override public int getInputEventCount(int which) {
1358         return mInputEventCounter.getCountLocked(which);
1359     }
1360 
getPhoneOnTime(long batteryRealtime, int which)1361     @Override public long getPhoneOnTime(long batteryRealtime, int which) {
1362         return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
1363     }
1364 
getPhoneSignalStrengthTime(int strengthBin, long batteryRealtime, int which)1365     @Override public long getPhoneSignalStrengthTime(int strengthBin,
1366             long batteryRealtime, int which) {
1367         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
1368                 batteryRealtime, which);
1369     }
1370 
getPhoneSignalScanningTime( long batteryRealtime, int which)1371     @Override public long getPhoneSignalScanningTime(
1372             long batteryRealtime, int which) {
1373         return mPhoneSignalScanningTimer.getTotalTimeLocked(
1374                 batteryRealtime, which);
1375     }
1376 
getPhoneSignalStrengthCount(int dataType, int which)1377     @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
1378         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
1379     }
1380 
getPhoneDataConnectionTime(int dataType, long batteryRealtime, int which)1381     @Override public long getPhoneDataConnectionTime(int dataType,
1382             long batteryRealtime, int which) {
1383         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
1384                 batteryRealtime, which);
1385     }
1386 
getPhoneDataConnectionCount(int dataType, int which)1387     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
1388         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
1389     }
1390 
getWifiOnTime(long batteryRealtime, int which)1391     @Override public long getWifiOnTime(long batteryRealtime, int which) {
1392         return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
1393     }
1394 
getWifiRunningTime(long batteryRealtime, int which)1395     @Override public long getWifiRunningTime(long batteryRealtime, int which) {
1396         return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
1397     }
1398 
getBluetoothOnTime(long batteryRealtime, int which)1399     @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
1400         return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
1401     }
1402 
getIsOnBattery()1403     @Override public boolean getIsOnBattery() {
1404         return mOnBattery;
1405     }
1406 
getUidStats()1407     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
1408         return mUidStats;
1409     }
1410 
1411     /**
1412      * The statistics associated with a particular uid.
1413      */
1414     public final class Uid extends BatteryStats.Uid {
1415 
1416         final int mUid;
1417         long mLoadedTcpBytesReceived;
1418         long mLoadedTcpBytesSent;
1419         long mCurrentTcpBytesReceived;
1420         long mCurrentTcpBytesSent;
1421         long mTcpBytesReceivedAtLastUnplug;
1422         long mTcpBytesSentAtLastUnplug;
1423 
1424         // These are not saved/restored when parcelling, since we want
1425         // to return from the parcel with a snapshot of the state.
1426         long mStartedTcpBytesReceived = -1;
1427         long mStartedTcpBytesSent = -1;
1428 
1429         boolean mWifiTurnedOn;
1430         StopwatchTimer mWifiTurnedOnTimer;
1431 
1432         boolean mFullWifiLockOut;
1433         StopwatchTimer mFullWifiLockTimer;
1434 
1435         boolean mScanWifiLockOut;
1436         StopwatchTimer mScanWifiLockTimer;
1437 
1438         boolean mWifiMulticastEnabled;
1439         StopwatchTimer mWifiMulticastTimer;
1440 
1441         boolean mAudioTurnedOn;
1442         StopwatchTimer mAudioTurnedOnTimer;
1443 
1444         boolean mVideoTurnedOn;
1445         StopwatchTimer mVideoTurnedOnTimer;
1446 
1447         Counter[] mUserActivityCounters;
1448 
1449         /**
1450          * The statistics we have collected for this uid's wake locks.
1451          */
1452         final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>();
1453 
1454         /**
1455          * The statistics we have collected for this uid's sensor activations.
1456          */
1457         final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>();
1458 
1459         /**
1460          * The statistics we have collected for this uid's processes.
1461          */
1462         final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>();
1463 
1464         /**
1465          * The statistics we have collected for this uid's processes.
1466          */
1467         final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>();
1468 
Uid(int uid)1469         public Uid(int uid) {
1470             mUid = uid;
1471             mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables);
1472             mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables);
1473             mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
1474             mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
1475                     null, mUnpluggables);
1476             mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables);
1477             mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables);
1478         }
1479 
1480         @Override
getWakelockStats()1481         public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
1482             return mWakelockStats;
1483         }
1484 
1485         @Override
getSensorStats()1486         public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() {
1487             return mSensorStats;
1488         }
1489 
1490         @Override
getProcessStats()1491         public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
1492             return mProcessStats;
1493         }
1494 
1495         @Override
getPackageStats()1496         public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
1497             return mPackageStats;
1498         }
1499 
1500         @Override
getUid()1501         public int getUid() {
1502             return mUid;
1503         }
1504 
1505         @Override
getTcpBytesReceived(int which)1506         public long getTcpBytesReceived(int which) {
1507             if (which == STATS_LAST) {
1508                 return mLoadedTcpBytesReceived;
1509             } else {
1510                 long current = computeCurrentTcpBytesReceived();
1511                 if (which == STATS_UNPLUGGED) {
1512                     current -= mTcpBytesReceivedAtLastUnplug;
1513                 } else if (which == STATS_TOTAL) {
1514                     current += mLoadedTcpBytesReceived;
1515                 }
1516                 return current;
1517             }
1518         }
1519 
computeCurrentTcpBytesReceived()1520         public long computeCurrentTcpBytesReceived() {
1521             return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
1522                     ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
1523         }
1524 
1525         @Override
getTcpBytesSent(int which)1526         public long getTcpBytesSent(int which) {
1527             if (which == STATS_LAST) {
1528                 return mLoadedTcpBytesSent;
1529             } else {
1530                 long current = computeCurrentTcpBytesSent();
1531                 if (which == STATS_UNPLUGGED) {
1532                     current -= mTcpBytesSentAtLastUnplug;
1533                 } else if (which == STATS_TOTAL) {
1534                     current += mLoadedTcpBytesSent;
1535                 }
1536                 return current;
1537             }
1538         }
1539 
1540         @Override
noteWifiTurnedOnLocked()1541         public void noteWifiTurnedOnLocked() {
1542             if (!mWifiTurnedOn) {
1543                 mWifiTurnedOn = true;
1544                 mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
1545             }
1546         }
1547 
1548         @Override
noteWifiTurnedOffLocked()1549         public void noteWifiTurnedOffLocked() {
1550             if (mWifiTurnedOn) {
1551                 mWifiTurnedOn = false;
1552                 mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
1553             }
1554         }
1555 
1556         @Override
noteFullWifiLockAcquiredLocked()1557         public void noteFullWifiLockAcquiredLocked() {
1558             if (!mFullWifiLockOut) {
1559                 mFullWifiLockOut = true;
1560                 mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
1561             }
1562         }
1563 
1564         @Override
noteVideoTurnedOnLocked()1565         public void noteVideoTurnedOnLocked() {
1566             if (!mVideoTurnedOn) {
1567                 mVideoTurnedOn = true;
1568                 mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
1569             }
1570         }
1571 
1572         @Override
noteVideoTurnedOffLocked()1573         public void noteVideoTurnedOffLocked() {
1574             if (mVideoTurnedOn) {
1575                 mVideoTurnedOn = false;
1576                 mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
1577             }
1578         }
1579 
1580         @Override
noteAudioTurnedOnLocked()1581         public void noteAudioTurnedOnLocked() {
1582             if (!mAudioTurnedOn) {
1583                 mAudioTurnedOn = true;
1584                 mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
1585             }
1586         }
1587 
1588         @Override
noteAudioTurnedOffLocked()1589         public void noteAudioTurnedOffLocked() {
1590             if (mAudioTurnedOn) {
1591                 mAudioTurnedOn = false;
1592                 mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
1593             }
1594         }
1595 
1596         @Override
noteFullWifiLockReleasedLocked()1597         public void noteFullWifiLockReleasedLocked() {
1598             if (mFullWifiLockOut) {
1599                 mFullWifiLockOut = false;
1600                 mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
1601             }
1602         }
1603 
1604         @Override
noteScanWifiLockAcquiredLocked()1605         public void noteScanWifiLockAcquiredLocked() {
1606             if (!mScanWifiLockOut) {
1607                 mScanWifiLockOut = true;
1608                 mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
1609             }
1610         }
1611 
1612         @Override
noteScanWifiLockReleasedLocked()1613         public void noteScanWifiLockReleasedLocked() {
1614             if (mScanWifiLockOut) {
1615                 mScanWifiLockOut = false;
1616                 mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
1617             }
1618         }
1619 
1620         @Override
noteWifiMulticastEnabledLocked()1621         public void noteWifiMulticastEnabledLocked() {
1622             if (!mWifiMulticastEnabled) {
1623                 mWifiMulticastEnabled = true;
1624                 mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this);
1625             }
1626         }
1627 
1628         @Override
noteWifiMulticastDisabledLocked()1629         public void noteWifiMulticastDisabledLocked() {
1630             if (mWifiMulticastEnabled) {
1631                 mWifiMulticastEnabled = false;
1632                 mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this);
1633             }
1634         }
1635 
1636         @Override
getWifiTurnedOnTime(long batteryRealtime, int which)1637         public long getWifiTurnedOnTime(long batteryRealtime, int which) {
1638             return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
1639         }
1640 
1641         @Override
getAudioTurnedOnTime(long batteryRealtime, int which)1642         public long getAudioTurnedOnTime(long batteryRealtime, int which) {
1643             return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
1644         }
1645 
1646         @Override
getVideoTurnedOnTime(long batteryRealtime, int which)1647         public long getVideoTurnedOnTime(long batteryRealtime, int which) {
1648             return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
1649         }
1650 
1651         @Override
getFullWifiLockTime(long batteryRealtime, int which)1652         public long getFullWifiLockTime(long batteryRealtime, int which) {
1653             return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
1654         }
1655 
1656         @Override
getScanWifiLockTime(long batteryRealtime, int which)1657         public long getScanWifiLockTime(long batteryRealtime, int which) {
1658             return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
1659         }
1660 
1661         @Override
getWifiMulticastTime(long batteryRealtime, int which)1662         public long getWifiMulticastTime(long batteryRealtime, int which) {
1663             return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime,
1664                                                           which);
1665         }
1666 
1667         @Override
noteUserActivityLocked(int type)1668         public void noteUserActivityLocked(int type) {
1669             if (mUserActivityCounters == null) {
1670                 initUserActivityLocked();
1671             }
1672             if (type < 0) type = 0;
1673             else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1;
1674             mUserActivityCounters[type].stepLocked();
1675         }
1676 
1677         @Override
hasUserActivity()1678         public boolean hasUserActivity() {
1679             return mUserActivityCounters != null;
1680         }
1681 
1682         @Override
getUserActivityCount(int type, int which)1683         public int getUserActivityCount(int type, int which) {
1684             if (mUserActivityCounters == null) {
1685                 return 0;
1686             }
1687             return mUserActivityCounters[type].getCountLocked(which);
1688         }
1689 
initUserActivityLocked()1690         void initUserActivityLocked() {
1691             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
1692             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1693                 mUserActivityCounters[i] = new Counter(mUnpluggables);
1694             }
1695         }
1696 
computeCurrentTcpBytesSent()1697         public long computeCurrentTcpBytesSent() {
1698             return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
1699                     ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
1700         }
1701 
writeToParcelLocked(Parcel out, long batteryRealtime)1702         void writeToParcelLocked(Parcel out, long batteryRealtime) {
1703             out.writeInt(mWakelockStats.size());
1704             for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
1705                 out.writeString(wakelockEntry.getKey());
1706                 Uid.Wakelock wakelock = wakelockEntry.getValue();
1707                 wakelock.writeToParcelLocked(out, batteryRealtime);
1708             }
1709 
1710             out.writeInt(mSensorStats.size());
1711             for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) {
1712                 out.writeInt(sensorEntry.getKey());
1713                 Uid.Sensor sensor = sensorEntry.getValue();
1714                 sensor.writeToParcelLocked(out, batteryRealtime);
1715             }
1716 
1717             out.writeInt(mProcessStats.size());
1718             for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) {
1719                 out.writeString(procEntry.getKey());
1720                 Uid.Proc proc = procEntry.getValue();
1721                 proc.writeToParcelLocked(out);
1722             }
1723 
1724             out.writeInt(mPackageStats.size());
1725             for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
1726                 out.writeString(pkgEntry.getKey());
1727                 Uid.Pkg pkg = pkgEntry.getValue();
1728                 pkg.writeToParcelLocked(out);
1729             }
1730 
1731             out.writeLong(mLoadedTcpBytesReceived);
1732             out.writeLong(mLoadedTcpBytesSent);
1733             out.writeLong(computeCurrentTcpBytesReceived());
1734             out.writeLong(computeCurrentTcpBytesSent());
1735             out.writeLong(mTcpBytesReceivedAtLastUnplug);
1736             out.writeLong(mTcpBytesSentAtLastUnplug);
1737             mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime);
1738             mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
1739             mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime);
1740             mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime);
1741             mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
1742             mWifiMulticastTimer.writeToParcel(out, batteryRealtime);
1743             if (mUserActivityCounters == null) {
1744                 out.writeInt(0);
1745             } else {
1746                 out.writeInt(1);
1747                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1748                     mUserActivityCounters[i].writeToParcel(out);
1749                 }
1750             }
1751         }
1752 
readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in)1753         void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1754             int numWakelocks = in.readInt();
1755             mWakelockStats.clear();
1756             for (int j = 0; j < numWakelocks; j++) {
1757                 String wakelockName = in.readString();
1758                 Uid.Wakelock wakelock = new Wakelock();
1759                 wakelock.readFromParcelLocked(unpluggables, in);
1760                 mWakelockStats.put(wakelockName, wakelock);
1761             }
1762 
1763             int numSensors = in.readInt();
1764             mSensorStats.clear();
1765             for (int k = 0; k < numSensors; k++) {
1766                 int sensorNumber = in.readInt();
1767                 Uid.Sensor sensor = new Sensor(sensorNumber);
1768                 sensor.readFromParcelLocked(mUnpluggables, in);
1769                 mSensorStats.put(sensorNumber, sensor);
1770             }
1771 
1772             int numProcs = in.readInt();
1773             mProcessStats.clear();
1774             for (int k = 0; k < numProcs; k++) {
1775                 String processName = in.readString();
1776                 Uid.Proc proc = new Proc();
1777                 proc.readFromParcelLocked(in);
1778                 mProcessStats.put(processName, proc);
1779             }
1780 
1781             int numPkgs = in.readInt();
1782             mPackageStats.clear();
1783             for (int l = 0; l < numPkgs; l++) {
1784                 String packageName = in.readString();
1785                 Uid.Pkg pkg = new Pkg();
1786                 pkg.readFromParcelLocked(in);
1787                 mPackageStats.put(packageName, pkg);
1788             }
1789 
1790             mLoadedTcpBytesReceived = in.readLong();
1791             mLoadedTcpBytesSent = in.readLong();
1792             mCurrentTcpBytesReceived = in.readLong();
1793             mCurrentTcpBytesSent = in.readLong();
1794             mTcpBytesReceivedAtLastUnplug = in.readLong();
1795             mTcpBytesSentAtLastUnplug = in.readLong();
1796             mWifiTurnedOn = false;
1797             mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in);
1798             mFullWifiLockOut = false;
1799             mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in);
1800             mAudioTurnedOn = false;
1801             mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables, in);
1802             mVideoTurnedOn = false;
1803             mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables, in);
1804             mScanWifiLockOut = false;
1805             mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
1806             mWifiMulticastEnabled = false;
1807             mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
1808                     null, mUnpluggables, in);
1809             if (in.readInt() == 0) {
1810                 mUserActivityCounters = null;
1811             } else {
1812                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
1813                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1814                     mUserActivityCounters[i] = new Counter(mUnpluggables, in);
1815                 }
1816             }
1817         }
1818 
1819         /**
1820          * The statistics associated with a particular wake lock.
1821          */
1822         public final class Wakelock extends BatteryStats.Uid.Wakelock {
1823             /**
1824              * How long (in ms) this uid has been keeping the device partially awake.
1825              */
1826             StopwatchTimer mTimerPartial;
1827 
1828             /**
1829              * How long (in ms) this uid has been keeping the device fully awake.
1830              */
1831             StopwatchTimer mTimerFull;
1832 
1833             /**
1834              * How long (in ms) this uid has had a window keeping the device awake.
1835              */
1836             StopwatchTimer mTimerWindow;
1837 
1838             /**
1839              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
1840              * proper timer pool from the given BatteryStatsImpl object.
1841              *
1842              * @param in the Parcel to be read from.
1843              * return a new Timer, or null.
1844              */
readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, ArrayList<Unpluggable> unpluggables, Parcel in)1845             private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
1846                     ArrayList<Unpluggable> unpluggables, Parcel in) {
1847                 if (in.readInt() == 0) {
1848                     return null;
1849                 }
1850 
1851                 return new StopwatchTimer(type, pool, unpluggables, in);
1852             }
1853 
readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in)1854             void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1855                 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
1856                         mPartialTimers, unpluggables, in);
1857                 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
1858                         mFullTimers, unpluggables, in);
1859                 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
1860                         mWindowTimers, unpluggables, in);
1861             }
1862 
writeToParcelLocked(Parcel out, long batteryRealtime)1863             void writeToParcelLocked(Parcel out, long batteryRealtime) {
1864                 Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime);
1865                 Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime);
1866                 Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime);
1867             }
1868 
1869             @Override
getWakeTime(int type)1870             public Timer getWakeTime(int type) {
1871                 switch (type) {
1872                 case WAKE_TYPE_FULL: return mTimerFull;
1873                 case WAKE_TYPE_PARTIAL: return mTimerPartial;
1874                 case WAKE_TYPE_WINDOW: return mTimerWindow;
1875                 default: throw new IllegalArgumentException("type = " + type);
1876                 }
1877             }
1878         }
1879 
1880         public final class Sensor extends BatteryStats.Uid.Sensor {
1881             final int mHandle;
1882             StopwatchTimer mTimer;
1883 
Sensor(int handle)1884             public Sensor(int handle) {
1885                 mHandle = handle;
1886             }
1887 
readTimerFromParcel(ArrayList<Unpluggable> unpluggables, Parcel in)1888             private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
1889                     Parcel in) {
1890                 if (in.readInt() == 0) {
1891                     return null;
1892                 }
1893 
1894                 ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
1895                 if (pool == null) {
1896                     pool = new ArrayList<StopwatchTimer>();
1897                     mSensorTimers.put(mHandle, pool);
1898                 }
1899                 return new StopwatchTimer(0, pool, unpluggables, in);
1900             }
1901 
readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in)1902             void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1903                 mTimer = readTimerFromParcel(unpluggables, in);
1904             }
1905 
writeToParcelLocked(Parcel out, long batteryRealtime)1906             void writeToParcelLocked(Parcel out, long batteryRealtime) {
1907                 Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
1908             }
1909 
1910             @Override
getSensorTime()1911             public Timer getSensorTime() {
1912                 return mTimer;
1913             }
1914 
1915             @Override
getHandle()1916             public int getHandle() {
1917                 return mHandle;
1918             }
1919         }
1920 
1921         /**
1922          * The statistics associated with a particular process.
1923          */
1924         public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable {
1925             /**
1926              * Total time (in 1/100 sec) spent executing in user code.
1927              */
1928             long mUserTime;
1929 
1930             /**
1931              * Total time (in 1/100 sec) spent executing in kernel code.
1932              */
1933             long mSystemTime;
1934 
1935             /**
1936              * Number of times the process has been started.
1937              */
1938             int mStarts;
1939 
1940             /**
1941              * Amount of time the process was running in the foreground.
1942              */
1943             long mForegroundTime;
1944 
1945             /**
1946              * The amount of user time loaded from a previous save.
1947              */
1948             long mLoadedUserTime;
1949 
1950             /**
1951              * The amount of system time loaded from a previous save.
1952              */
1953             long mLoadedSystemTime;
1954 
1955             /**
1956              * The number of times the process has started from a previous save.
1957              */
1958             int mLoadedStarts;
1959 
1960             /**
1961              * The amount of foreground time loaded from a previous save.
1962              */
1963             long mLoadedForegroundTime;
1964 
1965             /**
1966              * The amount of user time loaded from the previous run.
1967              */
1968             long mLastUserTime;
1969 
1970             /**
1971              * The amount of system time loaded from the previous run.
1972              */
1973             long mLastSystemTime;
1974 
1975             /**
1976              * The number of times the process has started from the previous run.
1977              */
1978             int mLastStarts;
1979 
1980             /**
1981              * The amount of foreground time loaded from the previous run
1982              */
1983             long mLastForegroundTime;
1984 
1985             /**
1986              * The amount of user time when last unplugged.
1987              */
1988             long mUnpluggedUserTime;
1989 
1990             /**
1991              * The amount of system time when last unplugged.
1992              */
1993             long mUnpluggedSystemTime;
1994 
1995             /**
1996              * The number of times the process has started before unplugged.
1997              */
1998             int mUnpluggedStarts;
1999 
2000             /**
2001              * The amount of foreground time since unplugged.
2002              */
2003             long mUnpluggedForegroundTime;
2004 
2005             SamplingCounter[] mSpeedBins;
2006 
Proc()2007             Proc() {
2008                 mUnpluggables.add(this);
2009                 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
2010                 for (int i = 0; i < mSpeedBins.length; i++) {
2011                     mSpeedBins[i] = new SamplingCounter(mUnpluggables);
2012                 }
2013             }
2014 
unplug(long batteryUptime, long batteryRealtime)2015             public void unplug(long batteryUptime, long batteryRealtime) {
2016                 mUnpluggedUserTime = mUserTime;
2017                 mUnpluggedSystemTime = mSystemTime;
2018                 mUnpluggedStarts = mStarts;
2019                 mUnpluggedForegroundTime = mForegroundTime;
2020             }
2021 
plug(long batteryUptime, long batteryRealtime)2022             public void plug(long batteryUptime, long batteryRealtime) {
2023             }
2024 
writeToParcelLocked(Parcel out)2025             void writeToParcelLocked(Parcel out) {
2026                 final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
2027                 final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
2028 
2029                 out.writeLong(mUserTime);
2030                 out.writeLong(mSystemTime);
2031                 out.writeLong(mForegroundTime);
2032                 out.writeInt(mStarts);
2033                 out.writeLong(mLoadedUserTime);
2034                 out.writeLong(mLoadedSystemTime);
2035                 out.writeLong(mLoadedForegroundTime);
2036                 out.writeInt(mLoadedStarts);
2037                 out.writeLong(mLastUserTime);
2038                 out.writeLong(mLastSystemTime);
2039                 out.writeLong(mLastForegroundTime);
2040                 out.writeInt(mLastStarts);
2041                 out.writeLong(mUnpluggedUserTime);
2042                 out.writeLong(mUnpluggedSystemTime);
2043                 out.writeLong(mUnpluggedForegroundTime);
2044                 out.writeInt(mUnpluggedStarts);
2045 
2046                 out.writeInt(mSpeedBins.length);
2047                 for (int i = 0; i < mSpeedBins.length; i++) {
2048                     mSpeedBins[i].writeToParcel(out);
2049                 }
2050             }
2051 
readFromParcelLocked(Parcel in)2052             void readFromParcelLocked(Parcel in) {
2053                 mUserTime = in.readLong();
2054                 mSystemTime = in.readLong();
2055                 mForegroundTime = in.readLong();
2056                 mStarts = in.readInt();
2057                 mLoadedUserTime = in.readLong();
2058                 mLoadedSystemTime = in.readLong();
2059                 mLoadedForegroundTime = in.readLong();
2060                 mLoadedStarts = in.readInt();
2061                 mLastUserTime = in.readLong();
2062                 mLastSystemTime = in.readLong();
2063                 mLastForegroundTime = in.readLong();
2064                 mLastStarts = in.readInt();
2065                 mUnpluggedUserTime = in.readLong();
2066                 mUnpluggedSystemTime = in.readLong();
2067                 mUnpluggedForegroundTime = in.readLong();
2068                 mUnpluggedStarts = in.readInt();
2069 
2070                 int bins = in.readInt();
2071                 mSpeedBins = new SamplingCounter[bins];
2072                 for (int i = 0; i < bins; i++) {
2073                     mSpeedBins[i] = new SamplingCounter(mUnpluggables, in);
2074                 }
2075             }
2076 
getBatteryStats()2077             public BatteryStatsImpl getBatteryStats() {
2078                 return BatteryStatsImpl.this;
2079             }
2080 
addCpuTimeLocked(int utime, int stime)2081             public void addCpuTimeLocked(int utime, int stime) {
2082                 mUserTime += utime;
2083                 mSystemTime += stime;
2084             }
2085 
addForegroundTimeLocked(long ttime)2086             public void addForegroundTimeLocked(long ttime) {
2087                 mForegroundTime += ttime;
2088             }
2089 
incStartsLocked()2090             public void incStartsLocked() {
2091                 mStarts++;
2092             }
2093 
2094             @Override
getUserTime(int which)2095             public long getUserTime(int which) {
2096                 long val;
2097                 if (which == STATS_LAST) {
2098                     val = mLastUserTime;
2099                 } else {
2100                     val = mUserTime;
2101                     if (which == STATS_CURRENT) {
2102                         val -= mLoadedUserTime;
2103                     } else if (which == STATS_UNPLUGGED) {
2104                         val -= mUnpluggedUserTime;
2105                     }
2106                 }
2107                 return val;
2108             }
2109 
2110             @Override
getSystemTime(int which)2111             public long getSystemTime(int which) {
2112                 long val;
2113                 if (which == STATS_LAST) {
2114                     val = mLastSystemTime;
2115                 } else {
2116                     val = mSystemTime;
2117                     if (which == STATS_CURRENT) {
2118                         val -= mLoadedSystemTime;
2119                     } else if (which == STATS_UNPLUGGED) {
2120                         val -= mUnpluggedSystemTime;
2121                     }
2122                 }
2123                 return val;
2124             }
2125 
2126             @Override
getForegroundTime(int which)2127             public long getForegroundTime(int which) {
2128                 long val;
2129                 if (which == STATS_LAST) {
2130                     val = mLastForegroundTime;
2131                 } else {
2132                     val = mForegroundTime;
2133                     if (which == STATS_CURRENT) {
2134                         val -= mLoadedForegroundTime;
2135                     } else if (which == STATS_UNPLUGGED) {
2136                         val -= mUnpluggedForegroundTime;
2137                     }
2138                 }
2139                 return val;
2140             }
2141 
2142             @Override
getStarts(int which)2143             public int getStarts(int which) {
2144                 int val;
2145                 if (which == STATS_LAST) {
2146                     val = mLastStarts;
2147                 } else {
2148                     val = mStarts;
2149                     if (which == STATS_CURRENT) {
2150                         val -= mLoadedStarts;
2151                     } else if (which == STATS_UNPLUGGED) {
2152                         val -= mUnpluggedStarts;
2153                     }
2154                 }
2155                 return val;
2156             }
2157 
2158             /* Called by ActivityManagerService when CPU times are updated. */
addSpeedStepTimes(long[] values)2159             public void addSpeedStepTimes(long[] values) {
2160                 for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
2161                     mSpeedBins[i].addCountLocked(values[i]);
2162                 }
2163             }
2164 
2165             @Override
getTimeAtCpuSpeedStep(int speedStep, int which)2166             public long getTimeAtCpuSpeedStep(int speedStep, int which) {
2167                 if (speedStep < mSpeedBins.length) {
2168                     return mSpeedBins[speedStep].getCountLocked(which);
2169                 } else {
2170                     return 0;
2171                 }
2172             }
2173         }
2174 
2175         /**
2176          * The statistics associated with a particular package.
2177          */
2178         public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable {
2179             /**
2180              * Number of times this package has done something that could wake up the
2181              * device from sleep.
2182              */
2183             int mWakeups;
2184 
2185             /**
2186              * Number of things that could wake up the device loaded from a
2187              * previous save.
2188              */
2189             int mLoadedWakeups;
2190 
2191             /**
2192              * Number of things that could wake up the device as of the
2193              * last run.
2194              */
2195             int mLastWakeups;
2196 
2197             /**
2198              * Number of things that could wake up the device as of the
2199              * last run.
2200              */
2201             int mUnpluggedWakeups;
2202 
2203             /**
2204              * The statics we have collected for this package's services.
2205              */
2206             final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
2207 
Pkg()2208             Pkg() {
2209                 mUnpluggables.add(this);
2210             }
2211 
unplug(long batteryUptime, long batteryRealtime)2212             public void unplug(long batteryUptime, long batteryRealtime) {
2213                 mUnpluggedWakeups = mWakeups;
2214             }
2215 
plug(long batteryUptime, long batteryRealtime)2216             public void plug(long batteryUptime, long batteryRealtime) {
2217             }
2218 
readFromParcelLocked(Parcel in)2219             void readFromParcelLocked(Parcel in) {
2220                 mWakeups = in.readInt();
2221                 mLoadedWakeups = in.readInt();
2222                 mLastWakeups = in.readInt();
2223                 mUnpluggedWakeups = in.readInt();
2224 
2225                 int numServs = in.readInt();
2226                 mServiceStats.clear();
2227                 for (int m = 0; m < numServs; m++) {
2228                     String serviceName = in.readString();
2229                     Uid.Pkg.Serv serv = new Serv();
2230                     mServiceStats.put(serviceName, serv);
2231 
2232                     serv.readFromParcelLocked(in);
2233                 }
2234             }
2235 
writeToParcelLocked(Parcel out)2236             void writeToParcelLocked(Parcel out) {
2237                 out.writeInt(mWakeups);
2238                 out.writeInt(mLoadedWakeups);
2239                 out.writeInt(mLastWakeups);
2240                 out.writeInt(mUnpluggedWakeups);
2241 
2242                 out.writeInt(mServiceStats.size());
2243                 for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
2244                     out.writeString(servEntry.getKey());
2245                     Uid.Pkg.Serv serv = servEntry.getValue();
2246 
2247                     serv.writeToParcelLocked(out);
2248                 }
2249             }
2250 
2251             @Override
getServiceStats()2252             public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
2253                 return mServiceStats;
2254             }
2255 
2256             @Override
getWakeups(int which)2257             public int getWakeups(int which) {
2258                 int val;
2259                 if (which == STATS_LAST) {
2260                     val = mLastWakeups;
2261                 } else {
2262                     val = mWakeups;
2263                     if (which == STATS_CURRENT) {
2264                         val -= mLoadedWakeups;
2265                     } else if (which == STATS_UNPLUGGED) {
2266                         val -= mUnpluggedWakeups;
2267                     }
2268                 }
2269 
2270                 return val;
2271             }
2272 
2273             /**
2274              * The statistics associated with a particular service.
2275              */
2276             public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable {
2277                 /**
2278                  * Total time (ms in battery uptime) the service has been left started.
2279                  */
2280                 long mStartTime;
2281 
2282                 /**
2283                  * If service has been started and not yet stopped, this is
2284                  * when it was started.
2285                  */
2286                 long mRunningSince;
2287 
2288                 /**
2289                  * True if we are currently running.
2290                  */
2291                 boolean mRunning;
2292 
2293                 /**
2294                  * Total number of times startService() has been called.
2295                  */
2296                 int mStarts;
2297 
2298                 /**
2299                  * Total time (ms in battery uptime) the service has been left launched.
2300                  */
2301                 long mLaunchedTime;
2302 
2303                 /**
2304                  * If service has been launched and not yet exited, this is
2305                  * when it was launched (ms in battery uptime).
2306                  */
2307                 long mLaunchedSince;
2308 
2309                 /**
2310                  * True if we are currently launched.
2311                  */
2312                 boolean mLaunched;
2313 
2314                 /**
2315                  * Total number times the service has been launched.
2316                  */
2317                 int mLaunches;
2318 
2319                 /**
2320                  * The amount of time spent started loaded from a previous save
2321                  * (ms in battery uptime).
2322                  */
2323                 long mLoadedStartTime;
2324 
2325                 /**
2326                  * The number of starts loaded from a previous save.
2327                  */
2328                 int mLoadedStarts;
2329 
2330                 /**
2331                  * The number of launches loaded from a previous save.
2332                  */
2333                 int mLoadedLaunches;
2334 
2335                 /**
2336                  * The amount of time spent started as of the last run (ms
2337                  * in battery uptime).
2338                  */
2339                 long mLastStartTime;
2340 
2341                 /**
2342                  * The number of starts as of the last run.
2343                  */
2344                 int mLastStarts;
2345 
2346                 /**
2347                  * The number of launches as of the last run.
2348                  */
2349                 int mLastLaunches;
2350 
2351                 /**
2352                  * The amount of time spent started when last unplugged (ms
2353                  * in battery uptime).
2354                  */
2355                 long mUnpluggedStartTime;
2356 
2357                 /**
2358                  * The number of starts when last unplugged.
2359                  */
2360                 int mUnpluggedStarts;
2361 
2362                 /**
2363                  * The number of launches when last unplugged.
2364                  */
2365                 int mUnpluggedLaunches;
2366 
Serv()2367                 Serv() {
2368                     mUnpluggables.add(this);
2369                 }
2370 
unplug(long batteryUptime, long batteryRealtime)2371                 public void unplug(long batteryUptime, long batteryRealtime) {
2372                     mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
2373                     mUnpluggedStarts = mStarts;
2374                     mUnpluggedLaunches = mLaunches;
2375                 }
2376 
plug(long batteryUptime, long batteryRealtime)2377                 public void plug(long batteryUptime, long batteryRealtime) {
2378                 }
2379 
readFromParcelLocked(Parcel in)2380                 void readFromParcelLocked(Parcel in) {
2381                     mStartTime = in.readLong();
2382                     mRunningSince = in.readLong();
2383                     mRunning = in.readInt() != 0;
2384                     mStarts = in.readInt();
2385                     mLaunchedTime = in.readLong();
2386                     mLaunchedSince = in.readLong();
2387                     mLaunched = in.readInt() != 0;
2388                     mLaunches = in.readInt();
2389                     mLoadedStartTime = in.readLong();
2390                     mLoadedStarts = in.readInt();
2391                     mLoadedLaunches = in.readInt();
2392                     mLastStartTime = in.readLong();
2393                     mLastStarts = in.readInt();
2394                     mLastLaunches = in.readInt();
2395                     mUnpluggedStartTime = in.readLong();
2396                     mUnpluggedStarts = in.readInt();
2397                     mUnpluggedLaunches = in.readInt();
2398                 }
2399 
writeToParcelLocked(Parcel out)2400                 void writeToParcelLocked(Parcel out) {
2401                     out.writeLong(mStartTime);
2402                     out.writeLong(mRunningSince);
2403                     out.writeInt(mRunning ? 1 : 0);
2404                     out.writeInt(mStarts);
2405                     out.writeLong(mLaunchedTime);
2406                     out.writeLong(mLaunchedSince);
2407                     out.writeInt(mLaunched ? 1 : 0);
2408                     out.writeInt(mLaunches);
2409                     out.writeLong(mLoadedStartTime);
2410                     out.writeInt(mLoadedStarts);
2411                     out.writeInt(mLoadedLaunches);
2412                     out.writeLong(mLastStartTime);
2413                     out.writeInt(mLastStarts);
2414                     out.writeInt(mLastLaunches);
2415                     out.writeLong(mUnpluggedStartTime);
2416                     out.writeInt(mUnpluggedStarts);
2417                     out.writeInt(mUnpluggedLaunches);
2418                 }
2419 
getLaunchTimeToNowLocked(long batteryUptime)2420                 long getLaunchTimeToNowLocked(long batteryUptime) {
2421                     if (!mLaunched) return mLaunchedTime;
2422                     return mLaunchedTime + batteryUptime - mLaunchedSince;
2423                 }
2424 
getStartTimeToNowLocked(long batteryUptime)2425                 long getStartTimeToNowLocked(long batteryUptime) {
2426                     if (!mRunning) return mStartTime;
2427                     return mStartTime + batteryUptime - mRunningSince;
2428                 }
2429 
startLaunchedLocked()2430                 public void startLaunchedLocked() {
2431                     if (!mLaunched) {
2432                         mLaunches++;
2433                         mLaunchedSince = getBatteryUptimeLocked();
2434                         mLaunched = true;
2435                     }
2436                 }
2437 
stopLaunchedLocked()2438                 public void stopLaunchedLocked() {
2439                     if (mLaunched) {
2440                         long time = getBatteryUptimeLocked() - mLaunchedSince;
2441                         if (time > 0) {
2442                             mLaunchedTime += time;
2443                         } else {
2444                             mLaunches--;
2445                         }
2446                         mLaunched = false;
2447                     }
2448                 }
2449 
startRunningLocked()2450                 public void startRunningLocked() {
2451                     if (!mRunning) {
2452                         mStarts++;
2453                         mRunningSince = getBatteryUptimeLocked();
2454                         mRunning = true;
2455                     }
2456                 }
2457 
stopRunningLocked()2458                 public void stopRunningLocked() {
2459                     if (mRunning) {
2460                         long time = getBatteryUptimeLocked() - mRunningSince;
2461                         if (time > 0) {
2462                             mStartTime += time;
2463                         } else {
2464                             mStarts--;
2465                         }
2466                         mRunning = false;
2467                     }
2468                 }
2469 
getBatteryStats()2470                 public BatteryStatsImpl getBatteryStats() {
2471                     return BatteryStatsImpl.this;
2472                 }
2473 
2474                 @Override
getLaunches(int which)2475                 public int getLaunches(int which) {
2476                     int val;
2477 
2478                     if (which == STATS_LAST) {
2479                         val = mLastLaunches;
2480                     } else {
2481                         val = mLaunches;
2482                         if (which == STATS_CURRENT) {
2483                             val -= mLoadedLaunches;
2484                         } else if (which == STATS_UNPLUGGED) {
2485                             val -= mUnpluggedLaunches;
2486                         }
2487                     }
2488 
2489                     return val;
2490                 }
2491 
2492                 @Override
getStartTime(long now, int which)2493                 public long getStartTime(long now, int which) {
2494                     long val;
2495                     if (which == STATS_LAST) {
2496                         val = mLastStartTime;
2497                     } else {
2498                         val = getStartTimeToNowLocked(now);
2499                         if (which == STATS_CURRENT) {
2500                             val -= mLoadedStartTime;
2501                         } else if (which == STATS_UNPLUGGED) {
2502                             val -= mUnpluggedStartTime;
2503                         }
2504                     }
2505 
2506                     return val;
2507                 }
2508 
2509                 @Override
getStarts(int which)2510                 public int getStarts(int which) {
2511                     int val;
2512                     if (which == STATS_LAST) {
2513                         val = mLastStarts;
2514                     } else {
2515                         val = mStarts;
2516                         if (which == STATS_CURRENT) {
2517                             val -= mLoadedStarts;
2518                         } else if (which == STATS_UNPLUGGED) {
2519                             val -= mUnpluggedStarts;
2520                         }
2521                     }
2522 
2523                     return val;
2524                 }
2525             }
2526 
getBatteryStats()2527             public BatteryStatsImpl getBatteryStats() {
2528                 return BatteryStatsImpl.this;
2529             }
2530 
incWakeupsLocked()2531             public void incWakeupsLocked() {
2532                 mWakeups++;
2533             }
2534 
newServiceStatsLocked()2535             final Serv newServiceStatsLocked() {
2536                 return new Serv();
2537             }
2538         }
2539 
2540         /**
2541          * Retrieve the statistics object for a particular process, creating
2542          * if needed.
2543          */
getProcessStatsLocked(String name)2544         public Proc getProcessStatsLocked(String name) {
2545             Proc ps = mProcessStats.get(name);
2546             if (ps == null) {
2547                 ps = new Proc();
2548                 mProcessStats.put(name, ps);
2549             }
2550 
2551             return ps;
2552         }
2553 
2554         /**
2555          * Retrieve the statistics object for a particular service, creating
2556          * if needed.
2557          */
getPackageStatsLocked(String name)2558         public Pkg getPackageStatsLocked(String name) {
2559             Pkg ps = mPackageStats.get(name);
2560             if (ps == null) {
2561                 ps = new Pkg();
2562                 mPackageStats.put(name, ps);
2563             }
2564 
2565             return ps;
2566         }
2567 
2568         /**
2569          * Retrieve the statistics object for a particular service, creating
2570          * if needed.
2571          */
getServiceStatsLocked(String pkg, String serv)2572         public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
2573             Pkg ps = getPackageStatsLocked(pkg);
2574             Pkg.Serv ss = ps.mServiceStats.get(serv);
2575             if (ss == null) {
2576                 ss = ps.newServiceStatsLocked();
2577                 ps.mServiceStats.put(serv, ss);
2578             }
2579 
2580             return ss;
2581         }
2582 
getWakeTimerLocked(String name, int type)2583         public StopwatchTimer getWakeTimerLocked(String name, int type) {
2584             Wakelock wl = mWakelockStats.get(name);
2585             if (wl == null) {
2586                 wl = new Wakelock();
2587                 mWakelockStats.put(name, wl);
2588             }
2589             StopwatchTimer t = null;
2590             switch (type) {
2591                 case WAKE_TYPE_PARTIAL:
2592                     t = wl.mTimerPartial;
2593                     if (t == null) {
2594                         t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
2595                         wl.mTimerPartial = t;
2596                     }
2597                     return t;
2598                 case WAKE_TYPE_FULL:
2599                     t = wl.mTimerFull;
2600                     if (t == null) {
2601                         t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
2602                         wl.mTimerFull = t;
2603                     }
2604                     return t;
2605                 case WAKE_TYPE_WINDOW:
2606                     t = wl.mTimerWindow;
2607                     if (t == null) {
2608                         t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
2609                         wl.mTimerWindow = t;
2610                     }
2611                     return t;
2612                 default:
2613                     throw new IllegalArgumentException("type=" + type);
2614             }
2615         }
2616 
getSensorTimerLocked(int sensor, boolean create)2617         public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
2618             Sensor se = mSensorStats.get(sensor);
2619             if (se == null) {
2620                 if (!create) {
2621                     return null;
2622                 }
2623                 se = new Sensor(sensor);
2624                 mSensorStats.put(sensor, se);
2625             }
2626             StopwatchTimer t = se.mTimer;
2627             if (t != null) {
2628                 return t;
2629             }
2630             ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
2631             if (timers == null) {
2632                 timers = new ArrayList<StopwatchTimer>();
2633                 mSensorTimers.put(sensor, timers);
2634             }
2635             t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables);
2636             se.mTimer = t;
2637             return t;
2638         }
2639 
noteStartWakeLocked(String name, int type)2640         public void noteStartWakeLocked(String name, int type) {
2641             StopwatchTimer t = getWakeTimerLocked(name, type);
2642             if (t != null) {
2643                 t.startRunningLocked(BatteryStatsImpl.this);
2644             }
2645         }
2646 
noteStopWakeLocked(String name, int type)2647         public void noteStopWakeLocked(String name, int type) {
2648             StopwatchTimer t = getWakeTimerLocked(name, type);
2649             if (t != null) {
2650                 t.stopRunningLocked(BatteryStatsImpl.this);
2651             }
2652         }
2653 
noteStartSensor(int sensor)2654         public void noteStartSensor(int sensor) {
2655             StopwatchTimer t = getSensorTimerLocked(sensor, true);
2656             if (t != null) {
2657                 t.startRunningLocked(BatteryStatsImpl.this);
2658             }
2659         }
2660 
noteStopSensor(int sensor)2661         public void noteStopSensor(int sensor) {
2662             // Don't create a timer if one doesn't already exist
2663             StopwatchTimer t = getSensorTimerLocked(sensor, false);
2664             if (t != null) {
2665                 t.stopRunningLocked(BatteryStatsImpl.this);
2666             }
2667         }
2668 
noteStartGps()2669         public void noteStartGps() {
2670             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
2671             if (t != null) {
2672                 t.startRunningLocked(BatteryStatsImpl.this);
2673             }
2674         }
2675 
noteStopGps()2676         public void noteStopGps() {
2677             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
2678             if (t != null) {
2679                 t.stopRunningLocked(BatteryStatsImpl.this);
2680             }
2681         }
2682 
getBatteryStats()2683         public BatteryStatsImpl getBatteryStats() {
2684             return BatteryStatsImpl.this;
2685         }
2686     }
2687 
BatteryStatsImpl(String filename)2688     public BatteryStatsImpl(String filename) {
2689         mFile = new File(filename);
2690         mBackupFile = new File(filename + ".bak");
2691         mStartCount++;
2692         mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables);
2693         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2694             mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables);
2695         }
2696         mInputEventCounter = new Counter(mUnpluggables);
2697         mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables);
2698         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2699             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
2700         }
2701         mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables);
2702         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2703             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
2704         }
2705         mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables);
2706         mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables);
2707         mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables);
2708         mOnBattery = mOnBatteryInternal = false;
2709         mTrackBatteryPastUptime = 0;
2710         mTrackBatteryPastRealtime = 0;
2711         mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
2712         mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
2713         mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
2714         mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
2715         mDischargeStartLevel = 0;
2716         mDischargeCurrentLevel = 0;
2717     }
2718 
BatteryStatsImpl(Parcel p)2719     public BatteryStatsImpl(Parcel p) {
2720         mFile = mBackupFile = null;
2721         readFromParcel(p);
2722     }
2723 
setNumSpeedSteps(int steps)2724     public void setNumSpeedSteps(int steps) {
2725         if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
2726     }
2727 
setRadioScanningTimeout(long timeout)2728     public void setRadioScanningTimeout(long timeout) {
2729         if (mPhoneSignalScanningTimer != null) {
2730             mPhoneSignalScanningTimer.setTimeout(timeout);
2731         }
2732     }
2733 
2734     @Override
getStartCount()2735     public int getStartCount() {
2736         return mStartCount;
2737     }
2738 
isOnBattery()2739     public boolean isOnBattery() {
2740         return mOnBattery;
2741     }
2742 
setOnBattery(boolean onBattery, int level)2743     public void setOnBattery(boolean onBattery, int level) {
2744         synchronized(this) {
2745             updateKernelWakelocksLocked();
2746             if (mOnBattery != onBattery) {
2747                 mOnBattery = mOnBatteryInternal = onBattery;
2748 
2749                 long uptime = SystemClock.uptimeMillis() * 1000;
2750                 long mSecRealtime = SystemClock.elapsedRealtime();
2751                 long realtime = mSecRealtime * 1000;
2752                 if (onBattery) {
2753                     mTrackBatteryUptimeStart = uptime;
2754                     mTrackBatteryRealtimeStart = realtime;
2755                     mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
2756                     mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
2757                     mDischargeCurrentLevel = mDischargeStartLevel = level;
2758                     doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
2759                 } else {
2760                     mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
2761                     mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
2762                     mDischargeCurrentLevel = level;
2763                     doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
2764                 }
2765                 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
2766                     if (mFile != null) {
2767                         writeLocked();
2768                     }
2769                 }
2770             }
2771         }
2772     }
2773 
recordCurrentLevel(int level)2774     public void recordCurrentLevel(int level) {
2775         mDischargeCurrentLevel = level;
2776     }
2777 
updateKernelWakelocksLocked()2778     public void updateKernelWakelocksLocked() {
2779         Map<String, KernelWakelockStats> m = readKernelWakelockStats();
2780 
2781         if (m == null) {
2782             // Not crashing might make board bringup easier.
2783             Log.w(TAG, "Couldn't get kernel wake lock stats");
2784             return;
2785         }
2786 
2787         for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
2788             String name = ent.getKey();
2789             KernelWakelockStats kws = ent.getValue();
2790 
2791             SamplingTimer kwlt = mKernelWakelockStats.get(name);
2792             if (kwlt == null) {
2793                 kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
2794                         true /* track reported values */);
2795                 mKernelWakelockStats.put(name, kwlt);
2796             }
2797             kwlt.updateCurrentReportedCount(kws.mCount);
2798             kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
2799             kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
2800         }
2801 
2802         if (m.size() != mKernelWakelockStats.size()) {
2803             // Set timers to stale if they didn't appear in /proc/wakelocks this time.
2804             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
2805                 SamplingTimer st = ent.getValue();
2806                 if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
2807                     st.setStale();
2808                 }
2809             }
2810         }
2811     }
2812 
getAwakeTimeBattery()2813     public long getAwakeTimeBattery() {
2814         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
2815     }
2816 
getAwakeTimePlugged()2817     public long getAwakeTimePlugged() {
2818         return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
2819     }
2820 
2821     @Override
computeUptime(long curTime, int which)2822     public long computeUptime(long curTime, int which) {
2823         switch (which) {
2824             case STATS_TOTAL: return mUptime + (curTime-mUptimeStart);
2825             case STATS_LAST: return mLastUptime;
2826             case STATS_CURRENT: return (curTime-mUptimeStart);
2827             case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
2828         }
2829         return 0;
2830     }
2831 
2832     @Override
computeRealtime(long curTime, int which)2833     public long computeRealtime(long curTime, int which) {
2834         switch (which) {
2835             case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart);
2836             case STATS_LAST: return mLastRealtime;
2837             case STATS_CURRENT: return (curTime-mRealtimeStart);
2838             case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
2839         }
2840         return 0;
2841     }
2842 
2843     @Override
computeBatteryUptime(long curTime, int which)2844     public long computeBatteryUptime(long curTime, int which) {
2845         switch (which) {
2846             case STATS_TOTAL:
2847                 return mBatteryUptime + getBatteryUptime(curTime);
2848             case STATS_LAST:
2849                 return mBatteryLastUptime;
2850             case STATS_CURRENT:
2851                 return getBatteryUptime(curTime);
2852             case STATS_UNPLUGGED:
2853                 return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
2854         }
2855         return 0;
2856     }
2857 
2858     @Override
computeBatteryRealtime(long curTime, int which)2859     public long computeBatteryRealtime(long curTime, int which) {
2860         switch (which) {
2861             case STATS_TOTAL:
2862                 return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
2863             case STATS_LAST:
2864                 return mBatteryLastRealtime;
2865             case STATS_CURRENT:
2866                 return getBatteryRealtimeLocked(curTime);
2867             case STATS_UNPLUGGED:
2868                 return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
2869         }
2870         return 0;
2871     }
2872 
getBatteryUptimeLocked(long curTime)2873     long getBatteryUptimeLocked(long curTime) {
2874         long time = mTrackBatteryPastUptime;
2875         if (mOnBatteryInternal) {
2876             time += curTime - mTrackBatteryUptimeStart;
2877         }
2878         return time;
2879     }
2880 
getBatteryUptimeLocked()2881     long getBatteryUptimeLocked() {
2882         return getBatteryUptime(SystemClock.uptimeMillis() * 1000);
2883     }
2884 
2885     @Override
getBatteryUptime(long curTime)2886     public long getBatteryUptime(long curTime) {
2887         return getBatteryUptimeLocked(curTime);
2888     }
2889 
getBatteryRealtimeLocked(long curTime)2890     long getBatteryRealtimeLocked(long curTime) {
2891         long time = mTrackBatteryPastRealtime;
2892         if (mOnBatteryInternal) {
2893             time += curTime - mTrackBatteryRealtimeStart;
2894         }
2895         return time;
2896     }
2897 
2898     @Override
getBatteryRealtime(long curTime)2899     public long getBatteryRealtime(long curTime) {
2900         return getBatteryRealtimeLocked(curTime);
2901     }
2902 
getTcpBytes(long current, long[] dataBytes, int which)2903     private long getTcpBytes(long current, long[] dataBytes, int which) {
2904         if (which == STATS_LAST) {
2905             return dataBytes[STATS_LAST];
2906         } else {
2907             if (which == STATS_UNPLUGGED) {
2908                 if (dataBytes[STATS_UNPLUGGED] < 0) {
2909                     return dataBytes[STATS_LAST];
2910                 } else {
2911                     return current - dataBytes[STATS_UNPLUGGED];
2912                 }
2913             } else if (which == STATS_TOTAL) {
2914                 return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_TOTAL];
2915             }
2916             return current - dataBytes[STATS_CURRENT];
2917         }
2918     }
2919 
2920     /** Only STATS_UNPLUGGED works properly */
getMobileTcpBytesSent(int which)2921     public long getMobileTcpBytesSent(int which) {
2922         return getTcpBytes(NetStat.getMobileTxBytes(), mMobileDataTx, which);
2923     }
2924 
2925     /** Only STATS_UNPLUGGED works properly */
getMobileTcpBytesReceived(int which)2926     public long getMobileTcpBytesReceived(int which) {
2927         return getTcpBytes(NetStat.getMobileRxBytes(), mMobileDataRx, which);
2928     }
2929 
2930     /** Only STATS_UNPLUGGED works properly */
getTotalTcpBytesSent(int which)2931     public long getTotalTcpBytesSent(int which) {
2932         return getTcpBytes(NetStat.getTotalTxBytes(), mTotalDataTx, which);
2933     }
2934 
2935     /** Only STATS_UNPLUGGED works properly */
getTotalTcpBytesReceived(int which)2936     public long getTotalTcpBytesReceived(int which) {
2937         return getTcpBytes(NetStat.getTotalRxBytes(), mTotalDataRx, which);
2938     }
2939 
2940     @Override
getDischargeStartLevel()2941     public int getDischargeStartLevel() {
2942         synchronized(this) {
2943             return getDischargeStartLevelLocked();
2944         }
2945     }
2946 
getDischargeStartLevelLocked()2947     public int getDischargeStartLevelLocked() {
2948             return mDischargeStartLevel;
2949     }
2950 
2951     @Override
getDischargeCurrentLevel()2952     public int getDischargeCurrentLevel() {
2953         synchronized(this) {
2954             return getDischargeCurrentLevelLocked();
2955         }
2956     }
2957 
getDischargeCurrentLevelLocked()2958     public int getDischargeCurrentLevelLocked() {
2959             return mDischargeCurrentLevel;
2960     }
2961 
2962     @Override
getCpuSpeedSteps()2963     public int getCpuSpeedSteps() {
2964         return sNumSpeedSteps;
2965     }
2966 
2967     /**
2968      * Retrieve the statistics object for a particular uid, creating if needed.
2969      */
getUidStatsLocked(int uid)2970     public Uid getUidStatsLocked(int uid) {
2971         Uid u = mUidStats.get(uid);
2972         if (u == null) {
2973             u = new Uid(uid);
2974             mUidStats.put(uid, u);
2975         }
2976         return u;
2977     }
2978 
2979     /**
2980      * Remove the statistics object for a particular uid.
2981      */
removeUidStatsLocked(int uid)2982     public void removeUidStatsLocked(int uid) {
2983         mUidStats.remove(uid);
2984     }
2985 
2986     /**
2987      * Retrieve the statistics object for a particular process, creating
2988      * if needed.
2989      */
getProcessStatsLocked(int uid, String name)2990     public Uid.Proc getProcessStatsLocked(int uid, String name) {
2991         Uid u = getUidStatsLocked(uid);
2992         return u.getProcessStatsLocked(name);
2993     }
2994 
2995     /**
2996      * Retrieve the statistics object for a particular process, given
2997      * the name of the process.
2998      * @param name process name
2999      * @return the statistics object for the process
3000      */
getProcessStatsLocked(String name, int pid)3001     public Uid.Proc getProcessStatsLocked(String name, int pid) {
3002         int uid;
3003         if (mUidCache.containsKey(name)) {
3004             uid = mUidCache.get(name);
3005         } else {
3006             uid = Process.getUidForPid(pid);
3007             mUidCache.put(name, uid);
3008         }
3009         Uid u = getUidStatsLocked(uid);
3010         return u.getProcessStatsLocked(name);
3011     }
3012 
3013     /**
3014      * Retrieve the statistics object for a particular process, creating
3015      * if needed.
3016      */
getPackageStatsLocked(int uid, String pkg)3017     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
3018         Uid u = getUidStatsLocked(uid);
3019         return u.getPackageStatsLocked(pkg);
3020     }
3021 
3022     /**
3023      * Retrieve the statistics object for a particular service, creating
3024      * if needed.
3025      */
getServiceStatsLocked(int uid, String pkg, String name)3026     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
3027         Uid u = getUidStatsLocked(uid);
3028         return u.getServiceStatsLocked(pkg, name);
3029     }
3030 
writeLocked()3031     public void writeLocked() {
3032         if ((mFile == null) || (mBackupFile == null)) {
3033             Log.w("BatteryStats", "writeLocked: no file associated with this instance");
3034             return;
3035         }
3036 
3037         // Keep the old file around until we know the new one has
3038         // been successfully written.
3039         if (mFile.exists()) {
3040             if (mBackupFile.exists()) {
3041                 mBackupFile.delete();
3042             }
3043             if (!mFile.renameTo(mBackupFile)) {
3044                 Log.w("BatteryStats", "Failed to back up file before writing new stats");
3045                 return;
3046             }
3047         }
3048 
3049         try {
3050             FileOutputStream stream = new FileOutputStream(mFile);
3051             Parcel out = Parcel.obtain();
3052             writeSummaryToParcel(out);
3053             stream.write(out.marshall());
3054             out.recycle();
3055 
3056             stream.flush();
3057             stream.close();
3058             mBackupFile.delete();
3059 
3060             mLastWriteTime = SystemClock.elapsedRealtime();
3061             return;
3062         } catch (IOException e) {
3063             Log.w("BatteryStats", "Error writing battery statistics", e);
3064         }
3065         if (mFile.exists()) {
3066             if (!mFile.delete()) {
3067                 Log.w(TAG, "Failed to delete mangled file " + mFile);
3068             }
3069         }
3070     }
3071 
readFully(FileInputStream stream)3072     static byte[] readFully(FileInputStream stream) throws java.io.IOException {
3073         int pos = 0;
3074         int avail = stream.available();
3075         byte[] data = new byte[avail];
3076         while (true) {
3077             int amt = stream.read(data, pos, data.length-pos);
3078             //Log.i("foo", "Read " + amt + " bytes at " + pos
3079             //        + " of avail " + data.length);
3080             if (amt <= 0) {
3081                 //Log.i("foo", "**** FINISHED READING: pos=" + pos
3082                 //        + " len=" + data.length);
3083                 return data;
3084             }
3085             pos += amt;
3086             avail = stream.available();
3087             if (avail > data.length-pos) {
3088                 byte[] newData = new byte[pos+avail];
3089                 System.arraycopy(data, 0, newData, 0, pos);
3090                 data = newData;
3091             }
3092         }
3093     }
3094 
readLocked()3095     public void readLocked() {
3096         if ((mFile == null) || (mBackupFile == null)) {
3097             Log.w("BatteryStats", "readLocked: no file associated with this instance");
3098             return;
3099         }
3100 
3101         mUidStats.clear();
3102 
3103         FileInputStream stream = null;
3104         if (mBackupFile.exists()) {
3105             try {
3106                 stream = new FileInputStream(mBackupFile);
3107             } catch (java.io.IOException e) {
3108                 // We'll try for the normal settings file.
3109             }
3110         }
3111 
3112         try {
3113             if (stream == null) {
3114                 if (!mFile.exists()) {
3115                     return;
3116                 }
3117                 stream = new FileInputStream(mFile);
3118             }
3119 
3120             byte[] raw = readFully(stream);
3121             Parcel in = Parcel.obtain();
3122             in.unmarshall(raw, 0, raw.length);
3123             in.setDataPosition(0);
3124             stream.close();
3125 
3126             readSummaryFromParcel(in);
3127         } catch(java.io.IOException e) {
3128             Log.e("BatteryStats", "Error reading battery statistics", e);
3129         }
3130     }
3131 
describeContents()3132     public int describeContents() {
3133         return 0;
3134     }
3135 
readSummaryFromParcel(Parcel in)3136     private void readSummaryFromParcel(Parcel in) {
3137         final int version = in.readInt();
3138         if (version != VERSION) {
3139             Log.w("BatteryStats", "readFromParcel: version got " + version
3140                 + ", expected " + VERSION + "; erasing old stats");
3141             return;
3142         }
3143 
3144         mStartCount = in.readInt();
3145         mBatteryUptime = in.readLong();
3146         mBatteryLastUptime = in.readLong();
3147         mBatteryRealtime = in.readLong();
3148         mBatteryLastRealtime = in.readLong();
3149         mUptime = in.readLong();
3150         mLastUptime = in.readLong();
3151         mRealtime = in.readLong();
3152         mLastRealtime = in.readLong();
3153         mDischargeStartLevel = in.readInt();
3154         mDischargeCurrentLevel = in.readInt();
3155 
3156         mStartCount++;
3157 
3158         mScreenOn = false;
3159         mScreenOnTimer.readSummaryFromParcelLocked(in);
3160         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3161             mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
3162         }
3163         mInputEventCounter.readSummaryFromParcelLocked(in);
3164         mPhoneOn = false;
3165         mPhoneOnTimer.readSummaryFromParcelLocked(in);
3166         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
3167             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
3168         }
3169         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
3170         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3171             mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
3172         }
3173         mWifiOn = false;
3174         mWifiOnTimer.readSummaryFromParcelLocked(in);
3175         mWifiRunning = false;
3176         mWifiRunningTimer.readSummaryFromParcelLocked(in);
3177         mBluetoothOn = false;
3178         mBluetoothOnTimer.readSummaryFromParcelLocked(in);
3179 
3180         int NKW = in.readInt();
3181         for (int ikw = 0; ikw < NKW; ikw++) {
3182             if (in.readInt() != 0) {
3183                 String kwltName = in.readString();
3184                 getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
3185             }
3186         }
3187 
3188         sNumSpeedSteps = in.readInt();
3189 
3190         final int NU = in.readInt();
3191         for (int iu = 0; iu < NU; iu++) {
3192             int uid = in.readInt();
3193             Uid u = new Uid(uid);
3194             mUidStats.put(uid, u);
3195 
3196             u.mWifiTurnedOn = false;
3197             u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in);
3198             u.mFullWifiLockOut = false;
3199             u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
3200             u.mAudioTurnedOn = false;
3201             u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in);
3202             u.mVideoTurnedOn = false;
3203             u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in);
3204             u.mScanWifiLockOut = false;
3205             u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
3206             u.mWifiMulticastEnabled = false;
3207             u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
3208 
3209             if (in.readInt() != 0) {
3210                 if (u.mUserActivityCounters == null) {
3211                     u.initUserActivityLocked();
3212                 }
3213                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
3214                     u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
3215                 }
3216             }
3217 
3218             int NW = in.readInt();
3219             for (int iw = 0; iw < NW; iw++) {
3220                 String wlName = in.readString();
3221                 if (in.readInt() != 0) {
3222                     u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
3223                 }
3224                 if (in.readInt() != 0) {
3225                     u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
3226                 }
3227                 if (in.readInt() != 0) {
3228                     u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
3229                 }
3230             }
3231 
3232             int NP = in.readInt();
3233             for (int is = 0; is < NP; is++) {
3234                 int seNumber = in.readInt();
3235                 if (in.readInt() != 0) {
3236                     u.getSensorTimerLocked(seNumber, true)
3237                             .readSummaryFromParcelLocked(in);
3238                 }
3239             }
3240 
3241             NP = in.readInt();
3242             for (int ip = 0; ip < NP; ip++) {
3243                 String procName = in.readString();
3244                 Uid.Proc p = u.getProcessStatsLocked(procName);
3245                 p.mUserTime = p.mLoadedUserTime = in.readLong();
3246                 p.mLastUserTime = in.readLong();
3247                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
3248                 p.mLastSystemTime = in.readLong();
3249                 p.mStarts = p.mLoadedStarts = in.readInt();
3250                 p.mLastStarts = in.readInt();
3251             }
3252 
3253             NP = in.readInt();
3254             for (int ip = 0; ip < NP; ip++) {
3255                 String pkgName = in.readString();
3256                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
3257                 p.mWakeups = p.mLoadedWakeups = in.readInt();
3258                 p.mLastWakeups = in.readInt();
3259                 final int NS = in.readInt();
3260                 for (int is = 0; is < NS; is++) {
3261                     String servName = in.readString();
3262                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
3263                     s.mStartTime = s.mLoadedStartTime = in.readLong();
3264                     s.mLastStartTime = in.readLong();
3265                     s.mStarts = s.mLoadedStarts = in.readInt();
3266                     s.mLastStarts = in.readInt();
3267                     s.mLaunches = s.mLoadedLaunches = in.readInt();
3268                     s.mLastLaunches = in.readInt();
3269                 }
3270             }
3271 
3272             u.mLoadedTcpBytesReceived = in.readLong();
3273             u.mLoadedTcpBytesSent = in.readLong();
3274         }
3275     }
3276 
3277     /**
3278      * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
3279      * disk.  This format does not allow a lossless round-trip.
3280      *
3281      * @param out the Parcel to be written to.
3282      */
writeSummaryToParcel(Parcel out)3283     public void writeSummaryToParcel(Parcel out) {
3284         final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
3285         final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
3286         final long NOW = getBatteryUptimeLocked(NOW_SYS);
3287         final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS);
3288 
3289         out.writeInt(VERSION);
3290 
3291         out.writeInt(mStartCount);
3292         out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL));
3293         out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT));
3294         out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL));
3295         out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT));
3296         out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL));
3297         out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT));
3298         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL));
3299         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT));
3300         out.writeInt(mDischargeStartLevel);
3301         out.writeInt(mDischargeCurrentLevel);
3302 
3303 
3304         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3305         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3306             mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
3307         }
3308         mInputEventCounter.writeSummaryFromParcelLocked(out);
3309         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3310         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
3311             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
3312         }
3313         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3314         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3315             mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
3316         }
3317         mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3318         mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3319         mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3320 
3321         out.writeInt(mKernelWakelockStats.size());
3322         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
3323             Timer kwlt = ent.getValue();
3324             if (kwlt != null) {
3325                 out.writeInt(1);
3326                 out.writeString(ent.getKey());
3327                 ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL);
3328             } else {
3329                 out.writeInt(0);
3330             }
3331         }
3332 
3333         out.writeInt(sNumSpeedSteps);
3334         final int NU = mUidStats.size();
3335         out.writeInt(NU);
3336         for (int iu = 0; iu < NU; iu++) {
3337             out.writeInt(mUidStats.keyAt(iu));
3338             Uid u = mUidStats.valueAt(iu);
3339 
3340             u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3341             u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3342             u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3343             u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3344             u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3345             u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3346 
3347             if (u.mUserActivityCounters == null) {
3348                 out.writeInt(0);
3349             } else {
3350                 out.writeInt(1);
3351                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
3352                     u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
3353                 }
3354             }
3355 
3356             int NW = u.mWakelockStats.size();
3357             out.writeInt(NW);
3358             if (NW > 0) {
3359                 for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent
3360                         : u.mWakelockStats.entrySet()) {
3361                     out.writeString(ent.getKey());
3362                     Uid.Wakelock wl = ent.getValue();
3363                     if (wl.mTimerFull != null) {
3364                         out.writeInt(1);
3365                         wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL);
3366                     } else {
3367                         out.writeInt(0);
3368                     }
3369                     if (wl.mTimerPartial != null) {
3370                         out.writeInt(1);
3371                         wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL);
3372                     } else {
3373                         out.writeInt(0);
3374                     }
3375                     if (wl.mTimerWindow != null) {
3376                         out.writeInt(1);
3377                         wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL);
3378                     } else {
3379                         out.writeInt(0);
3380                     }
3381                 }
3382             }
3383 
3384             int NSE = u.mSensorStats.size();
3385             out.writeInt(NSE);
3386             if (NSE > 0) {
3387                 for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent
3388                         : u.mSensorStats.entrySet()) {
3389                     out.writeInt(ent.getKey());
3390                     Uid.Sensor se = ent.getValue();
3391                     if (se.mTimer != null) {
3392                         out.writeInt(1);
3393                         se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL);
3394                     } else {
3395                         out.writeInt(0);
3396                     }
3397                 }
3398             }
3399 
3400             int NP = u.mProcessStats.size();
3401             out.writeInt(NP);
3402             if (NP > 0) {
3403                 for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent
3404                     : u.mProcessStats.entrySet()) {
3405                     out.writeString(ent.getKey());
3406                     Uid.Proc ps = ent.getValue();
3407                     out.writeLong(ps.mUserTime);
3408                     out.writeLong(ps.mUserTime - ps.mLoadedUserTime);
3409                     out.writeLong(ps.mSystemTime);
3410                     out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime);
3411                     out.writeInt(ps.mStarts);
3412                     out.writeInt(ps.mStarts - ps.mLoadedStarts);
3413                 }
3414             }
3415 
3416             NP = u.mPackageStats.size();
3417             out.writeInt(NP);
3418             if (NP > 0) {
3419                 for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
3420                     : u.mPackageStats.entrySet()) {
3421                     out.writeString(ent.getKey());
3422                     Uid.Pkg ps = ent.getValue();
3423                     out.writeInt(ps.mWakeups);
3424                     out.writeInt(ps.mWakeups - ps.mLoadedWakeups);
3425                     final int NS = ps.mServiceStats.size();
3426                     out.writeInt(NS);
3427                     if (NS > 0) {
3428                         for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
3429                                 : ps.mServiceStats.entrySet()) {
3430                             out.writeString(sent.getKey());
3431                             BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
3432                             long time = ss.getStartTimeToNowLocked(NOW);
3433                             out.writeLong(time);
3434                             out.writeLong(time - ss.mLoadedStartTime);
3435                             out.writeInt(ss.mStarts);
3436                             out.writeInt(ss.mStarts - ss.mLoadedStarts);
3437                             out.writeInt(ss.mLaunches);
3438                             out.writeInt(ss.mLaunches - ss.mLoadedLaunches);
3439                         }
3440                     }
3441                 }
3442             }
3443 
3444             out.writeLong(u.getTcpBytesReceived(STATS_TOTAL));
3445             out.writeLong(u.getTcpBytesSent(STATS_TOTAL));
3446         }
3447     }
3448 
readFromParcel(Parcel in)3449     public void readFromParcel(Parcel in) {
3450         readFromParcelLocked(in);
3451     }
3452 
readFromParcelLocked(Parcel in)3453     void readFromParcelLocked(Parcel in) {
3454         int magic = in.readInt();
3455         if (magic != MAGIC) {
3456             throw new ParcelFormatException("Bad magic number");
3457         }
3458 
3459         mStartCount = in.readInt();
3460         mBatteryUptime = in.readLong();
3461         mBatteryLastUptime = in.readLong();
3462         mBatteryRealtime = in.readLong();
3463         mBatteryLastRealtime = in.readLong();
3464         mScreenOn = false;
3465         mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in);
3466         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3467             mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in);
3468         }
3469         mInputEventCounter = new Counter(mUnpluggables, in);
3470         mPhoneOn = false;
3471         mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
3472         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
3473             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
3474         }
3475         mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in);
3476         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3477             mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
3478         }
3479         mWifiOn = false;
3480         mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
3481         mWifiRunning = false;
3482         mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
3483         mBluetoothOn = false;
3484         mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
3485         mUptime = in.readLong();
3486         mUptimeStart = in.readLong();
3487         mLastUptime = in.readLong();
3488         mRealtime = in.readLong();
3489         mRealtimeStart = in.readLong();
3490         mLastRealtime = in.readLong();
3491         mOnBattery = in.readInt() != 0;
3492         mOnBatteryInternal = false; // we are no longer really running.
3493         mTrackBatteryPastUptime = in.readLong();
3494         mTrackBatteryUptimeStart = in.readLong();
3495         mTrackBatteryPastRealtime = in.readLong();
3496         mTrackBatteryRealtimeStart = in.readLong();
3497         mUnpluggedBatteryUptime = in.readLong();
3498         mUnpluggedBatteryRealtime = in.readLong();
3499         mDischargeStartLevel = in.readInt();
3500         mDischargeCurrentLevel = in.readInt();
3501         mLastWriteTime = in.readLong();
3502 
3503         mMobileDataRx[STATS_LAST] = in.readLong();
3504         mMobileDataRx[STATS_UNPLUGGED] = -1;
3505         mMobileDataTx[STATS_LAST] = in.readLong();
3506         mMobileDataTx[STATS_UNPLUGGED] = -1;
3507         mTotalDataRx[STATS_LAST] = in.readLong();
3508         mTotalDataRx[STATS_UNPLUGGED] = -1;
3509         mTotalDataTx[STATS_LAST] = in.readLong();
3510         mTotalDataTx[STATS_UNPLUGGED] = -1;
3511 
3512         mRadioDataUptime = in.readLong();
3513         mRadioDataStart = -1;
3514 
3515         mBluetoothPingCount = in.readInt();
3516         mBluetoothPingStart = -1;
3517 
3518         mKernelWakelockStats.clear();
3519         int NKW = in.readInt();
3520         for (int ikw = 0; ikw < NKW; ikw++) {
3521             if (in.readInt() != 0) {
3522                 String wakelockName = in.readString();
3523                 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel
3524                 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in);
3525                 mKernelWakelockStats.put(wakelockName, kwlt);
3526             }
3527         }
3528 
3529         mPartialTimers.clear();
3530         mFullTimers.clear();
3531         mWindowTimers.clear();
3532 
3533         sNumSpeedSteps = in.readInt();
3534 
3535         int numUids = in.readInt();
3536         mUidStats.clear();
3537         for (int i = 0; i < numUids; i++) {
3538             int uid = in.readInt();
3539             Uid u = new Uid(uid);
3540             u.readFromParcelLocked(mUnpluggables, in);
3541             mUidStats.append(uid, u);
3542         }
3543     }
3544 
writeToParcel(Parcel out, int flags)3545     public void writeToParcel(Parcel out, int flags) {
3546         writeToParcelLocked(out, flags);
3547     }
3548 
3549     @SuppressWarnings("unused")
writeToParcelLocked(Parcel out, int flags)3550     void writeToParcelLocked(Parcel out, int flags) {
3551         final long uSecUptime = SystemClock.uptimeMillis() * 1000;
3552         final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
3553         final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
3554         final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
3555 
3556         out.writeInt(MAGIC);
3557         out.writeInt(mStartCount);
3558         out.writeLong(mBatteryUptime);
3559         out.writeLong(mBatteryLastUptime);
3560         out.writeLong(mBatteryRealtime);
3561         out.writeLong(mBatteryLastRealtime);
3562         mScreenOnTimer.writeToParcel(out, batteryRealtime);
3563         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3564             mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime);
3565         }
3566         mInputEventCounter.writeToParcel(out);
3567         mPhoneOnTimer.writeToParcel(out, batteryRealtime);
3568         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
3569             mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime);
3570         }
3571         mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime);
3572         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3573             mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
3574         }
3575         mWifiOnTimer.writeToParcel(out, batteryRealtime);
3576         mWifiRunningTimer.writeToParcel(out, batteryRealtime);
3577         mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
3578         out.writeLong(mUptime);
3579         out.writeLong(mUptimeStart);
3580         out.writeLong(mLastUptime);
3581         out.writeLong(mRealtime);
3582         out.writeLong(mRealtimeStart);
3583         out.writeLong(mLastRealtime);
3584         out.writeInt(mOnBattery ? 1 : 0);
3585         out.writeLong(batteryUptime);
3586         out.writeLong(mTrackBatteryUptimeStart);
3587         out.writeLong(batteryRealtime);
3588         out.writeLong(mTrackBatteryRealtimeStart);
3589         out.writeLong(mUnpluggedBatteryUptime);
3590         out.writeLong(mUnpluggedBatteryRealtime);
3591         out.writeInt(mDischargeStartLevel);
3592         out.writeInt(mDischargeCurrentLevel);
3593         out.writeLong(mLastWriteTime);
3594 
3595         out.writeLong(getMobileTcpBytesReceived(STATS_UNPLUGGED));
3596         out.writeLong(getMobileTcpBytesSent(STATS_UNPLUGGED));
3597         out.writeLong(getTotalTcpBytesReceived(STATS_UNPLUGGED));
3598         out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED));
3599 
3600         // Write radio uptime for data
3601         out.writeLong(getRadioDataUptime());
3602 
3603         out.writeInt(getBluetoothPingCount());
3604 
3605         out.writeInt(mKernelWakelockStats.size());
3606         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
3607             SamplingTimer kwlt = ent.getValue();
3608             if (kwlt != null) {
3609                 out.writeInt(1);
3610                 out.writeString(ent.getKey());
3611                 Timer.writeTimerToParcel(out, kwlt, batteryRealtime);
3612             } else {
3613                 out.writeInt(0);
3614             }
3615         }
3616 
3617         out.writeInt(sNumSpeedSteps);
3618 
3619         int size = mUidStats.size();
3620         out.writeInt(size);
3621         for (int i = 0; i < size; i++) {
3622             out.writeInt(mUidStats.keyAt(i));
3623             Uid uid = mUidStats.valueAt(i);
3624 
3625             uid.writeToParcelLocked(out, batteryRealtime);
3626         }
3627     }
3628 
3629     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
3630         new Parcelable.Creator<BatteryStatsImpl>() {
3631         public BatteryStatsImpl createFromParcel(Parcel in) {
3632             return new BatteryStatsImpl(in);
3633         }
3634 
3635         public BatteryStatsImpl[] newArray(int size) {
3636             return new BatteryStatsImpl[size];
3637         }
3638     };
3639 
dumpLocked(PrintWriter pw)3640     public void dumpLocked(PrintWriter pw) {
3641         if (DEBUG) {
3642             Printer pr = new PrintWriterPrinter(pw);
3643             pr.println("*** Screen timer:");
3644             mScreenOnTimer.logState(pr, "  ");
3645             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
3646                 pr.println("*** Screen brightness #" + i + ":");
3647                 mScreenBrightnessTimer[i].logState(pr, "  ");
3648             }
3649             pr.println("*** Input event counter:");
3650             mInputEventCounter.logState(pr, "  ");
3651             pr.println("*** Phone timer:");
3652             mPhoneOnTimer.logState(pr, "  ");
3653             for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
3654                 pr.println("*** Signal strength #" + i + ":");
3655                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
3656             }
3657             pr.println("*** Signal scanning :");
3658             mPhoneSignalScanningTimer.logState(pr, "  ");
3659             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
3660                 pr.println("*** Data connection type #" + i + ":");
3661                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
3662             }
3663             pr.println("*** Wifi timer:");
3664             mWifiOnTimer.logState(pr, "  ");
3665             pr.println("*** WifiRunning timer:");
3666             mWifiRunningTimer.logState(pr, "  ");
3667             pr.println("*** Bluetooth timer:");
3668             mBluetoothOnTimer.logState(pr, "  ");
3669         }
3670         super.dumpLocked(pw);
3671     }
3672 }
3673