BatteryStatsImpl.java revision cfc893d27a59bddbc5d0da0038e8313f6c379f86
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
17package com.android.internal.os;
18
19import android.bluetooth.BluetoothHeadset;
20import android.os.BatteryStats;
21import android.os.NetStat;
22import android.os.Parcel;
23import android.os.ParcelFormatException;
24import android.os.Parcelable;
25import android.os.Process;
26import android.os.SystemClock;
27import android.telephony.ServiceState;
28import android.telephony.SignalStrength;
29import android.telephony.TelephonyManager;
30import android.util.Log;
31import android.util.PrintWriterPrinter;
32import android.util.Printer;
33import android.util.SparseArray;
34
35import java.io.BufferedReader;
36import java.io.File;
37import java.io.FileInputStream;
38import java.io.FileOutputStream;
39import java.io.FileReader;
40import java.io.IOException;
41import java.io.PrintWriter;
42import java.util.ArrayList;
43import java.util.HashMap;
44import java.util.Iterator;
45import 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 */
52public 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 = 42;
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
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
211    public BatteryStatsImpl() {
212        mFile = mBackupFile = null;
213    }
214
215    public static interface Unpluggable {
216        void unplug(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
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
238        Counter(ArrayList<Unpluggable> unpluggables) {
239            unpluggables.add(this);
240        }
241
242        public void writeToParcel(Parcel out) {
243            out.writeInt(mCount);
244            out.writeInt(mLoadedCount);
245            out.writeInt(mLastCount);
246            out.writeInt(mUnpluggedCount);
247        }
248
249        public void unplug(long batteryUptime, long batteryRealtime) {
250            mUnpluggedCount = mCount = mPluggedCount;
251        }
252
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         */
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
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
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
297        void stepLocked() {
298            mCount++;
299        }
300
301        void writeSummaryFromParcelLocked(Parcel out) {
302            out.writeInt(mCount);
303            out.writeInt(mCount - mLoadedCount);
304        }
305
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
315        SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
316            super(unpluggables, in);
317        }
318
319        SamplingCounter(ArrayList<Unpluggable> unpluggables) {
320            super(unpluggables);
321        }
322
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         */
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
390        Timer(int type, ArrayList<Unpluggable> unpluggables) {
391            mType = type;
392            unpluggables.add(this);
393        }
394
395        protected abstract long computeRunTimeLocked(long curBatteryRealtime);
396
397        protected abstract int computeCurrentCountLocked();
398
399
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
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
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         */
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
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
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
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
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
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
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
571        SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
572                boolean trackReportedValues) {
573            super(0, unpluggables);
574            mTrackingReportedValues = trackReportedValues;
575            mInDischarge = inDischarge;
576        }
577
578        public void setStale() {
579            mTrackingReportedValues = false;
580            mUnpluggedReportedTotalTime = 0;
581            mUnpluggedReportedCount = 0;
582        }
583
584        public void setUpdateVersion(int version) {
585            mUpdateVersion = version;
586        }
587
588        public int getUpdateVersion() {
589            return mUpdateVersion;
590        }
591
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
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
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
621        public void plug(long batteryUptime, long batteryRealtime) {
622            super.plug(batteryUptime, batteryRealtime);
623            mInDischarge = false;
624        }
625
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
634        protected long computeRunTimeLocked(long curBatteryRealtime) {
635            return mTotalTime + (mInDischarge && mTrackingReportedValues
636                    ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
637        }
638
639        protected int computeCurrentCountLocked() {
640            return mCount + (mInDischarge && mTrackingReportedValues
641                    ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
642        }
643
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
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
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
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
698        StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
699                ArrayList<Unpluggable> unpluggables) {
700            super(type, unpluggables);
701            mTimerPool = timerPool;
702        }
703
704        void setTimeout(long timeout) {
705            mTimeout = timeout;
706        }
707
708        public void writeToParcel(Parcel out, long batteryRealtime) {
709            super.writeToParcel(out, batteryRealtime);
710            out.writeLong(mUpdateTime);
711        }
712
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
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
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
754        boolean isRunningLocked() {
755            return mNesting > 0;
756        }
757
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
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
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
821        protected int computeCurrentCountLocked() {
822            return mCount;
823        }
824
825        void readSummaryFromParcelLocked(Parcel in) {
826            super.readSummaryFromParcelLocked(in);
827            mNesting = 0;
828        }
829    }
830
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
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
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     */
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
952    private void doDataPlug(long[] dataTransfer, long currentBytes) {
953        dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED];
954        dataTransfer[STATS_UNPLUGGED] = -1;
955    }
956
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     */
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     */
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     */
991    public long getRadioDataUptime() {
992        if (mRadioDataStart == -1) {
993            return mRadioDataUptime;
994        } else {
995            return getCurrentRadioDataUptime() - mRadioDataStart;
996        }
997    }
998
999    private int getCurrentBluetoothPingCount() {
1000        if (mBtHeadset != null) {
1001            return mBtHeadset.getBatteryUsageHint();
1002        }
1003        return -1;
1004    }
1005
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
1015    public void setBtHeadset(BluetoothHeadset headset) {
1016        if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) {
1017            mBluetoothPingStart = getCurrentBluetoothPingCount();
1018        }
1019        mBtHeadset = headset;
1020    }
1021
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
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
1074    public void noteStartGps(int uid) {
1075        getUidStatsLocked(uid).noteStartGps();
1076    }
1077
1078    public void noteStopGps(int uid) {
1079        getUidStatsLocked(uid).noteStopGps();
1080    }
1081
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
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
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
1118    public void noteInputEventLocked() {
1119        mInputEventCounter.stepLocked();
1120    }
1121
1122    public void noteUserActivityLocked(int uid, int event) {
1123        getUidStatsLocked(uid).noteUserActivityLocked(event);
1124    }
1125
1126    public void notePhoneOnLocked() {
1127        if (!mPhoneOn) {
1128            mPhoneOn = true;
1129            mPhoneOnTimer.startRunningLocked(this);
1130        }
1131    }
1132
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     */
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
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
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
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
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
1263    public void noteAudioOnLocked(int uid) {
1264        if (!mAudioOn) {
1265            mAudioOn = true;
1266            mAudioOnTimer.startRunningLocked(this);
1267        }
1268        getUidStatsLocked(uid).noteAudioTurnedOnLocked();
1269    }
1270
1271    public void noteAudioOffLocked(int uid) {
1272        if (mAudioOn) {
1273            mAudioOn = false;
1274            mAudioOnTimer.stopRunningLocked(this);
1275        }
1276        getUidStatsLocked(uid).noteAudioTurnedOffLocked();
1277    }
1278
1279    public void noteVideoOnLocked(int uid) {
1280        if (!mVideoOn) {
1281            mVideoOn = true;
1282            mVideoOnTimer.startRunningLocked(this);
1283        }
1284        getUidStatsLocked(uid).noteVideoTurnedOnLocked();
1285    }
1286
1287    public void noteVideoOffLocked(int uid) {
1288        if (mVideoOn) {
1289            mVideoOn = false;
1290            mVideoOnTimer.stopRunningLocked(this);
1291        }
1292        getUidStatsLocked(uid).noteVideoTurnedOffLocked();
1293    }
1294
1295    public void noteWifiRunningLocked() {
1296        if (!mWifiRunning) {
1297            mWifiRunning = true;
1298            mWifiRunningTimer.startRunningLocked(this);
1299        }
1300    }
1301
1302    public void noteWifiStoppedLocked() {
1303        if (mWifiRunning) {
1304            mWifiRunning = false;
1305            mWifiRunningTimer.stopRunningLocked(this);
1306        }
1307    }
1308
1309    public void noteBluetoothOnLocked() {
1310        if (!mBluetoothOn) {
1311            mBluetoothOn = true;
1312            mBluetoothOnTimer.startRunningLocked(this);
1313        }
1314    }
1315
1316    public void noteBluetoothOffLocked() {
1317        if (mBluetoothOn) {
1318            mBluetoothOn = false;
1319            mBluetoothOnTimer.stopRunningLocked(this);
1320        }
1321    }
1322
1323    public void noteFullWifiLockAcquiredLocked(int uid) {
1324        getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked();
1325    }
1326
1327    public void noteFullWifiLockReleasedLocked(int uid) {
1328        getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
1329    }
1330
1331    public void noteScanWifiLockAcquiredLocked(int uid) {
1332        getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
1333    }
1334
1335    public void noteScanWifiLockReleasedLocked(int uid) {
1336        getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
1337    }
1338
1339    public void noteWifiMulticastEnabledLocked(int uid) {
1340        getUidStatsLocked(uid).noteWifiMulticastEnabledLocked();
1341    }
1342
1343    public void noteWifiMulticastDisabledLocked(int uid) {
1344        getUidStatsLocked(uid).noteWifiMulticastDisabledLocked();
1345    }
1346
1347    @Override public long getScreenOnTime(long batteryRealtime, int which) {
1348        return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
1349    }
1350
1351    @Override public long getScreenBrightnessTime(int brightnessBin,
1352            long batteryRealtime, int which) {
1353        return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
1354                batteryRealtime, which);
1355    }
1356
1357    @Override public int getInputEventCount(int which) {
1358        return mInputEventCounter.getCountLocked(which);
1359    }
1360
1361    @Override public long getPhoneOnTime(long batteryRealtime, int which) {
1362        return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
1363    }
1364
1365    @Override public long getPhoneSignalStrengthTime(int strengthBin,
1366            long batteryRealtime, int which) {
1367        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
1368                batteryRealtime, which);
1369    }
1370
1371    @Override public long getPhoneSignalScanningTime(
1372            long batteryRealtime, int which) {
1373        return mPhoneSignalScanningTimer.getTotalTimeLocked(
1374                batteryRealtime, which);
1375    }
1376
1377    @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
1378        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
1379    }
1380
1381    @Override public long getPhoneDataConnectionTime(int dataType,
1382            long batteryRealtime, int which) {
1383        return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
1384                batteryRealtime, which);
1385    }
1386
1387    @Override public int getPhoneDataConnectionCount(int dataType, int which) {
1388        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
1389    }
1390
1391    @Override public long getWifiOnTime(long batteryRealtime, int which) {
1392        return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
1393    }
1394
1395    @Override public long getWifiRunningTime(long batteryRealtime, int which) {
1396        return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
1397    }
1398
1399    @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
1400        return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
1401    }
1402
1403    @Override public boolean getIsOnBattery() {
1404        return mOnBattery;
1405    }
1406
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
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
1481        public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
1482            return mWakelockStats;
1483        }
1484
1485        @Override
1486        public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() {
1487            return mSensorStats;
1488        }
1489
1490        @Override
1491        public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
1492            return mProcessStats;
1493        }
1494
1495        @Override
1496        public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
1497            return mPackageStats;
1498        }
1499
1500        @Override
1501        public int getUid() {
1502            return mUid;
1503        }
1504
1505        @Override
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
1520        public long computeCurrentTcpBytesReceived() {
1521            return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
1522                    ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
1523        }
1524
1525        @Override
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
1541        public void noteWifiTurnedOnLocked() {
1542            if (!mWifiTurnedOn) {
1543                mWifiTurnedOn = true;
1544                mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
1545            }
1546        }
1547
1548        @Override
1549        public void noteWifiTurnedOffLocked() {
1550            if (mWifiTurnedOn) {
1551                mWifiTurnedOn = false;
1552                mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
1553            }
1554        }
1555
1556        @Override
1557        public void noteFullWifiLockAcquiredLocked() {
1558            if (!mFullWifiLockOut) {
1559                mFullWifiLockOut = true;
1560                mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
1561            }
1562        }
1563
1564        @Override
1565        public void noteVideoTurnedOnLocked() {
1566            if (!mVideoTurnedOn) {
1567                mVideoTurnedOn = true;
1568                mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
1569            }
1570        }
1571
1572        @Override
1573        public void noteVideoTurnedOffLocked() {
1574            if (mVideoTurnedOn) {
1575                mVideoTurnedOn = false;
1576                mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
1577            }
1578        }
1579
1580        @Override
1581        public void noteAudioTurnedOnLocked() {
1582            if (!mAudioTurnedOn) {
1583                mAudioTurnedOn = true;
1584                mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
1585            }
1586        }
1587
1588        @Override
1589        public void noteAudioTurnedOffLocked() {
1590            if (mAudioTurnedOn) {
1591                mAudioTurnedOn = false;
1592                mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
1593            }
1594        }
1595
1596        @Override
1597        public void noteFullWifiLockReleasedLocked() {
1598            if (mFullWifiLockOut) {
1599                mFullWifiLockOut = false;
1600                mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
1601            }
1602        }
1603
1604        @Override
1605        public void noteScanWifiLockAcquiredLocked() {
1606            if (!mScanWifiLockOut) {
1607                mScanWifiLockOut = true;
1608                mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
1609            }
1610        }
1611
1612        @Override
1613        public void noteScanWifiLockReleasedLocked() {
1614            if (mScanWifiLockOut) {
1615                mScanWifiLockOut = false;
1616                mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
1617            }
1618        }
1619
1620        @Override
1621        public void noteWifiMulticastEnabledLocked() {
1622            if (!mWifiMulticastEnabled) {
1623                mWifiMulticastEnabled = true;
1624                mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this);
1625            }
1626        }
1627
1628        @Override
1629        public void noteWifiMulticastDisabledLocked() {
1630            if (mWifiMulticastEnabled) {
1631                mWifiMulticastEnabled = false;
1632                mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this);
1633            }
1634        }
1635
1636        @Override
1637        public long getWifiTurnedOnTime(long batteryRealtime, int which) {
1638            return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
1639        }
1640
1641        @Override
1642        public long getAudioTurnedOnTime(long batteryRealtime, int which) {
1643            return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
1644        }
1645
1646        @Override
1647        public long getVideoTurnedOnTime(long batteryRealtime, int which) {
1648            return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
1649        }
1650
1651        @Override
1652        public long getFullWifiLockTime(long batteryRealtime, int which) {
1653            return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
1654        }
1655
1656        @Override
1657        public long getScanWifiLockTime(long batteryRealtime, int which) {
1658            return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
1659        }
1660
1661        @Override
1662        public long getWifiMulticastTime(long batteryRealtime, int which) {
1663            return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime,
1664                                                          which);
1665        }
1666
1667        @Override
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
1678        public boolean hasUserActivity() {
1679            return mUserActivityCounters != null;
1680        }
1681
1682        @Override
1683        public int getUserActivityCount(int type, int which) {
1684            if (mUserActivityCounters == null) {
1685                return 0;
1686            }
1687            return mUserActivityCounters[type].getCountLocked(which);
1688        }
1689
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
1697        public long computeCurrentTcpBytesSent() {
1698            return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
1699                    ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
1700        }
1701
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
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             */
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
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
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
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
1884            public Sensor(int handle) {
1885                mHandle = handle;
1886            }
1887
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
1902            void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1903                mTimer = readTimerFromParcel(unpluggables, in);
1904            }
1905
1906            void writeToParcelLocked(Parcel out, long batteryRealtime) {
1907                Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
1908            }
1909
1910            @Override
1911            public Timer getSensorTime() {
1912                return mTimer;
1913            }
1914
1915            @Override
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
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
2015            public void unplug(long batteryUptime, long batteryRealtime) {
2016                mUnpluggedUserTime = mUserTime;
2017                mUnpluggedSystemTime = mSystemTime;
2018                mUnpluggedStarts = mStarts;
2019                mUnpluggedForegroundTime = mForegroundTime;
2020            }
2021
2022            public void plug(long batteryUptime, long batteryRealtime) {
2023            }
2024
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
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
2077            public BatteryStatsImpl getBatteryStats() {
2078                return BatteryStatsImpl.this;
2079            }
2080
2081            public void addCpuTimeLocked(int utime, int stime) {
2082                mUserTime += utime;
2083                mSystemTime += stime;
2084            }
2085
2086            public void addForegroundTimeLocked(long ttime) {
2087                mForegroundTime += ttime;
2088            }
2089
2090            public void incStartsLocked() {
2091                mStarts++;
2092            }
2093
2094            @Override
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
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
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
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. */
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
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
2208            Pkg() {
2209                mUnpluggables.add(this);
2210            }
2211
2212            public void unplug(long batteryUptime, long batteryRealtime) {
2213                mUnpluggedWakeups = mWakeups;
2214            }
2215
2216            public void plug(long batteryUptime, long batteryRealtime) {
2217            }
2218
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
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
2252            public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
2253                return mServiceStats;
2254            }
2255
2256            @Override
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
2367                Serv() {
2368                    mUnpluggables.add(this);
2369                }
2370
2371                public void unplug(long batteryUptime, long batteryRealtime) {
2372                    mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
2373                    mUnpluggedStarts = mStarts;
2374                    mUnpluggedLaunches = mLaunches;
2375                }
2376
2377                public void plug(long batteryUptime, long batteryRealtime) {
2378                }
2379
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
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
2420                long getLaunchTimeToNowLocked(long batteryUptime) {
2421                    if (!mLaunched) return mLaunchedTime;
2422                    return mLaunchedTime + batteryUptime - mLaunchedSince;
2423                }
2424
2425                long getStartTimeToNowLocked(long batteryUptime) {
2426                    if (!mRunning) return mStartTime;
2427                    return mStartTime + batteryUptime - mRunningSince;
2428                }
2429
2430                public void startLaunchedLocked() {
2431                    if (!mLaunched) {
2432                        mLaunches++;
2433                        mLaunchedSince = getBatteryUptimeLocked();
2434                        mLaunched = true;
2435                    }
2436                }
2437
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
2450                public void startRunningLocked() {
2451                    if (!mRunning) {
2452                        mStarts++;
2453                        mRunningSince = getBatteryUptimeLocked();
2454                        mRunning = true;
2455                    }
2456                }
2457
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
2470                public BatteryStatsImpl getBatteryStats() {
2471                    return BatteryStatsImpl.this;
2472                }
2473
2474                @Override
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
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
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
2527            public BatteryStatsImpl getBatteryStats() {
2528                return BatteryStatsImpl.this;
2529            }
2530
2531            public void incWakeupsLocked() {
2532                mWakeups++;
2533            }
2534
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         */
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         */
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         */
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
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
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
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
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
2654        public void noteStartSensor(int sensor) {
2655            StopwatchTimer t = getSensorTimerLocked(sensor, true);
2656            if (t != null) {
2657                t.startRunningLocked(BatteryStatsImpl.this);
2658            }
2659        }
2660
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
2669        public void noteStartGps() {
2670            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
2671            if (t != null) {
2672                t.startRunningLocked(BatteryStatsImpl.this);
2673            }
2674        }
2675
2676        public void noteStopGps() {
2677            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
2678            if (t != null) {
2679                t.stopRunningLocked(BatteryStatsImpl.this);
2680            }
2681        }
2682
2683        public BatteryStatsImpl getBatteryStats() {
2684            return BatteryStatsImpl.this;
2685        }
2686    }
2687
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
2719    public BatteryStatsImpl(Parcel p) {
2720        mFile = mBackupFile = null;
2721        readFromParcel(p);
2722    }
2723
2724    public void setNumSpeedSteps(int steps) {
2725        if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
2726    }
2727
2728    public void setRadioScanningTimeout(long timeout) {
2729        if (mPhoneSignalScanningTimer != null) {
2730            mPhoneSignalScanningTimer.setTimeout(timeout);
2731        }
2732    }
2733
2734    @Override
2735    public int getStartCount() {
2736        return mStartCount;
2737    }
2738
2739    public boolean isOnBattery() {
2740        return mOnBattery;
2741    }
2742
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
2774    public void recordCurrentLevel(int level) {
2775        mDischargeCurrentLevel = level;
2776    }
2777
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
2813    public long getAwakeTimeBattery() {
2814        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
2815    }
2816
2817    public long getAwakeTimePlugged() {
2818        return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
2819    }
2820
2821    @Override
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
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
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
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
2873    long getBatteryUptimeLocked(long curTime) {
2874        long time = mTrackBatteryPastUptime;
2875        if (mOnBatteryInternal) {
2876            time += curTime - mTrackBatteryUptimeStart;
2877        }
2878        return time;
2879    }
2880
2881    long getBatteryUptimeLocked() {
2882        return getBatteryUptime(SystemClock.uptimeMillis() * 1000);
2883    }
2884
2885    @Override
2886    public long getBatteryUptime(long curTime) {
2887        return getBatteryUptimeLocked(curTime);
2888    }
2889
2890    long getBatteryRealtimeLocked(long curTime) {
2891        long time = mTrackBatteryPastRealtime;
2892        if (mOnBatteryInternal) {
2893            time += curTime - mTrackBatteryRealtimeStart;
2894        }
2895        return time;
2896    }
2897
2898    @Override
2899    public long getBatteryRealtime(long curTime) {
2900        return getBatteryRealtimeLocked(curTime);
2901    }
2902
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 */
2921    public long getMobileTcpBytesSent(int which) {
2922        return getTcpBytes(NetStat.getMobileTxBytes(), mMobileDataTx, which);
2923    }
2924
2925    /** Only STATS_UNPLUGGED works properly */
2926    public long getMobileTcpBytesReceived(int which) {
2927        return getTcpBytes(NetStat.getMobileRxBytes(), mMobileDataRx, which);
2928    }
2929
2930    /** Only STATS_UNPLUGGED works properly */
2931    public long getTotalTcpBytesSent(int which) {
2932        return getTcpBytes(NetStat.getTotalTxBytes(), mTotalDataTx, which);
2933    }
2934
2935    /** Only STATS_UNPLUGGED works properly */
2936    public long getTotalTcpBytesReceived(int which) {
2937        return getTcpBytes(NetStat.getTotalRxBytes(), mTotalDataRx, which);
2938    }
2939
2940    @Override
2941    public int getDischargeStartLevel() {
2942        synchronized(this) {
2943            return getDischargeStartLevelLocked();
2944        }
2945    }
2946
2947    public int getDischargeStartLevelLocked() {
2948            return mDischargeStartLevel;
2949    }
2950
2951    @Override
2952    public int getDischargeCurrentLevel() {
2953        synchronized(this) {
2954            return getDischargeCurrentLevelLocked();
2955        }
2956    }
2957
2958    public int getDischargeCurrentLevelLocked() {
2959            return mDischargeCurrentLevel;
2960    }
2961
2962    @Override
2963    public int getCpuSpeedSteps() {
2964        return sNumSpeedSteps;
2965    }
2966
2967    /**
2968     * Retrieve the statistics object for a particular uid, creating if needed.
2969     */
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     */
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     */
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     */
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     */
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     */
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
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
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
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
3132    public int describeContents() {
3133        return 0;
3134    }
3135
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     */
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
3449    public void readFromParcel(Parcel in) {
3450        readFromParcelLocked(in);
3451    }
3452
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
3545    public void writeToParcel(Parcel out, int flags) {
3546        writeToParcelLocked(out, flags);
3547    }
3548
3549    @SuppressWarnings("unused")
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
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