BatteryStatsImpl.java revision bed30e1b6ea4a1d71dbe5e731c274cc66974283a
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.os.BatteryStats;
20import android.os.NetStat;
21import android.os.Parcel;
22import android.os.ParcelFormatException;
23import android.os.Parcelable;
24import android.os.SystemClock;
25import android.telephony.TelephonyManager;
26import android.util.Log;
27import android.util.Printer;
28import android.util.SparseArray;
29
30import java.io.File;
31import java.io.FileInputStream;
32import java.io.FileOutputStream;
33import java.io.IOException;
34import java.util.ArrayList;
35import java.util.HashMap;
36import java.util.Map;
37
38/**
39 * All information we are collecting about things that can happen that impact
40 * battery life.  All times are represented in microseconds except where indicated
41 * otherwise.
42 */
43public final class BatteryStatsImpl extends BatteryStats {
44    private static final String TAG = "BatteryStatsImpl";
45    private static final boolean DEBUG = false;
46
47    // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
48    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
49
50    // Current on-disk Parcel version
51    private static final int VERSION = 32;
52
53    private final File mFile;
54    private final File mBackupFile;
55
56    /**
57     * The statistics we have collected organized by uids.
58     */
59    final SparseArray<BatteryStatsImpl.Uid> mUidStats =
60        new SparseArray<BatteryStatsImpl.Uid>();
61
62    // A set of pools of currently active timers.  When a timer is queried, we will divide the
63    // elapsed time by the number of active timers to arrive at that timer's share of the time.
64    // In order to do this, we must refresh each timer whenever the number of active timers
65    // changes.
66    final ArrayList<Timer> mPartialTimers = new ArrayList<Timer>();
67    final ArrayList<Timer> mFullTimers = new ArrayList<Timer>();
68    final ArrayList<Timer> mWindowTimers = new ArrayList<Timer>();
69    final SparseArray<ArrayList<Timer>> mSensorTimers
70            = new SparseArray<ArrayList<Timer>>();
71
72    // These are the objects that will want to do something when the device
73    // is unplugged from power.
74    final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
75
76    int mStartCount;
77
78    long mBatteryUptime;
79    long mBatteryLastUptime;
80    long mBatteryRealtime;
81    long mBatteryLastRealtime;
82
83    long mUptime;
84    long mUptimeStart;
85    long mLastUptime;
86    long mRealtime;
87    long mRealtimeStart;
88    long mLastRealtime;
89
90    boolean mScreenOn;
91    Timer mScreenOnTimer;
92
93    int mScreenBrightnessBin = -1;
94    final Timer[] mScreenBrightnessTimer = new Timer[NUM_SCREEN_BRIGHTNESS_BINS];
95
96    Counter mInputEventCounter;
97
98    boolean mPhoneOn;
99    Timer mPhoneOnTimer;
100
101    int mPhoneSignalStrengthBin = -1;
102    final Timer[] mPhoneSignalStrengthsTimer = new Timer[NUM_SIGNAL_STRENGTH_BINS];
103
104    int mPhoneDataConnectionType = -1;
105    final Timer[] mPhoneDataConnectionsTimer = new Timer[NUM_DATA_CONNECTION_TYPES];
106
107    boolean mWifiOn;
108    Timer mWifiOnTimer;
109    int mWifiOnUid = -1;
110
111    boolean mWifiRunning;
112    Timer mWifiRunningTimer;
113
114    boolean mBluetoothOn;
115    Timer mBluetoothOnTimer;
116
117    /**
118     * These provide time bases that discount the time the device is plugged
119     * in to power.
120     */
121    boolean mOnBattery;
122    boolean mOnBatteryInternal;
123    long mTrackBatteryPastUptime;
124    long mTrackBatteryUptimeStart;
125    long mTrackBatteryPastRealtime;
126    long mTrackBatteryRealtimeStart;
127
128    long mUnpluggedBatteryUptime;
129    long mUnpluggedBatteryRealtime;
130
131    /*
132     * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
133     */
134    int mUnpluggedStartLevel;
135    int mPluggedStartLevel;
136
137    long mLastWriteTime = 0; // Milliseconds
138
139    // For debugging
140    public BatteryStatsImpl() {
141        mFile = mBackupFile = null;
142    }
143
144    public static interface Unpluggable {
145        void unplug(long batteryUptime, long batteryRealtime);
146        void plug(long batteryUptime, long batteryRealtime);
147    }
148
149    /**
150     * State for keeping track of counting information.
151     */
152    public static final class Counter extends BatteryStats.Counter implements Unpluggable {
153        int mCount;
154        int mLoadedCount;
155        int mLastCount;
156        int mUnpluggedCount;
157        int mPluggedCount;
158
159        Counter(ArrayList<Unpluggable> unpluggables, Parcel in) {
160            mPluggedCount = mCount = in.readInt();
161            mLoadedCount = in.readInt();
162            mLastCount = in.readInt();
163            mUnpluggedCount = in.readInt();
164            unpluggables.add(this);
165        }
166
167        Counter(ArrayList<Unpluggable> unpluggables) {
168            unpluggables.add(this);
169        }
170
171        public void writeToParcel(Parcel out) {
172            out.writeInt(mCount);
173            out.writeInt(mLoadedCount);
174            out.writeInt(mLastCount);
175            out.writeInt(mUnpluggedCount);
176        }
177
178        public void unplug(long batteryUptime, long batteryRealtime) {
179            mUnpluggedCount = mCount = mPluggedCount;
180        }
181
182        public void plug(long batteryUptime, long batteryRealtime) {
183            mPluggedCount = mCount;
184        }
185
186        /**
187         * Writes a possibly null Counter to a Parcel.
188         *
189         * @param out the Parcel to be written to.
190         * @param counter a Counter, or null.
191         */
192        public static void writeCounterToParcel(Parcel out, Counter counter) {
193            if (counter == null) {
194                out.writeInt(0); // indicates null
195                return;
196            }
197            out.writeInt(1); // indicates non-null
198
199            counter.writeToParcel(out);
200        }
201
202        @Override
203        public int getCount(int which) {
204            int val;
205            if (which == STATS_LAST) {
206                val = mLastCount;
207            } else {
208                val = mCount;
209                if (which == STATS_UNPLUGGED) {
210                    val -= mUnpluggedCount;
211                } else if (which != STATS_TOTAL) {
212                    val -= mLoadedCount;
213                }
214            }
215
216            return val;
217        }
218
219        public void logState(Printer pw, String prefix) {
220            pw.println(prefix + "mCount=" + mCount
221                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
222                    + " mUnpluggedCount=" + mUnpluggedCount
223                    + " mPluggedCount=" + mPluggedCount);
224        }
225
226        void stepLocked() {
227            mCount++;
228        }
229
230        void writeSummaryFromParcelLocked(Parcel out) {
231            out.writeInt(mCount);
232            out.writeInt(mCount - mLoadedCount);
233        }
234
235        void readSummaryFromParcelLocked(Parcel in) {
236            mCount = mLoadedCount = in.readInt();
237            mLastCount = in.readInt();
238            mUnpluggedCount = mPluggedCount = mCount;
239        }
240    }
241
242    /**
243     * State for keeping track of timing information.
244     */
245    public static final class Timer extends BatteryStats.Timer implements Unpluggable {
246        final int mType;
247        final ArrayList<Timer> mTimerPool;
248
249        int mNesting;
250
251        int mCount;
252        int mLoadedCount;
253        int mLastCount;
254        int mUnpluggedCount;
255
256        // Times are in microseconds for better accuracy when dividing by the
257        // lock count, and are in "battery realtime" units.
258
259        /**
260         * The total time we have accumulated since the start of the original
261         * boot, to the last time something interesting happened in the
262         * current run.
263         */
264        long mTotalTime;
265
266        /**
267         * The total time we loaded for the previous runs.  Subtract this from
268         * mTotalTime to find the time for the current run of the system.
269         */
270        long mLoadedTime;
271
272        /**
273         * The run time of the last run of the system, as loaded from the
274         * saved data.
275         */
276        long mLastTime;
277
278        /**
279         * The value of mTotalTime when unplug() was last called.  Subtract
280         * this from mTotalTime to find the time since the last unplug from
281         * power.
282         */
283        long mUnpluggedTime;
284
285        /**
286         * The last time at which we updated the timer.  If mNesting is > 0,
287         * subtract this from the current battery time to find the amount of
288         * time we have been running since we last computed an update.
289         */
290        long mUpdateTime;
291
292        /**
293         * The total time at which the timer was acquired, to determine if
294         * was actually held for an interesting duration.
295         */
296        long mAcquireTime;
297
298        Timer(int type, ArrayList<Timer> timerPool,
299                ArrayList<Unpluggable> unpluggables, Parcel in) {
300            mType = type;
301            mTimerPool = timerPool;
302            mCount = in.readInt();
303            mLoadedCount = in.readInt();
304            mLastCount = in.readInt();
305            mUnpluggedCount = in.readInt();
306            mTotalTime = in.readLong();
307            mLoadedTime = in.readLong();
308            mLastTime = in.readLong();
309            mUpdateTime = in.readLong();
310            mUnpluggedTime = in.readLong();
311            unpluggables.add(this);
312        }
313
314        Timer(int type, ArrayList<Timer> timerPool,
315                ArrayList<Unpluggable> unpluggables) {
316            mType = type;
317            mTimerPool = timerPool;
318            unpluggables.add(this);
319        }
320
321        public void writeToParcel(Parcel out, long batteryRealtime) {
322            out.writeInt(mCount);
323            out.writeInt(mLoadedCount);
324            out.writeInt(mLastCount);
325            out.writeInt(mUnpluggedCount);
326            out.writeLong(computeRunTimeLocked(batteryRealtime));
327            out.writeLong(mLoadedTime);
328            out.writeLong(mLastTime);
329            out.writeLong(mUpdateTime);
330            out.writeLong(mUnpluggedTime);
331        }
332
333        public void unplug(long batteryUptime, long batteryRealtime) {
334            if (DEBUG && mType < 0) {
335                Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime
336                        + " old mUnpluggedTime=" + mUnpluggedTime
337                        + " old mUnpluggedCount=" + mUnpluggedCount);
338            }
339            mUnpluggedTime = computeRunTimeLocked(batteryRealtime);
340            mUnpluggedCount = mCount;
341            if (DEBUG && mType < 0) {
342                Log.v(TAG, "unplug #" + mType
343                        + ": new mUnpluggedTime=" + mUnpluggedTime
344                        + " new mUnpluggedCount=" + mUnpluggedCount);
345            }
346        }
347
348        public void plug(long batteryUptime, long batteryRealtime) {
349            if (mNesting > 0) {
350                if (DEBUG && mType < 0) {
351                    Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
352                            + " old mTotalTime=" + mTotalTime
353                            + " old mUpdateTime=" + mUpdateTime);
354                }
355                mTotalTime = computeRunTimeLocked(batteryRealtime);
356                mUpdateTime = batteryRealtime;
357                if (DEBUG && mType < 0) {
358                    Log.v(TAG, "plug #" + mType
359                            + ": new mTotalTime=" + mTotalTime
360                            + " old mUpdateTime=" + mUpdateTime);
361                }
362            }
363        }
364
365        /**
366         * Writes a possibly null Timer to a Parcel.
367         *
368         * @param out the Parcel to be written to.
369         * @param timer a Timer, or null.
370         */
371        public static void writeTimerToParcel(Parcel out, Timer timer,
372                long batteryRealtime) {
373            if (timer == null) {
374                out.writeInt(0); // indicates null
375                return;
376            }
377            out.writeInt(1); // indicates non-null
378
379            timer.writeToParcel(out, batteryRealtime);
380        }
381
382        @Override
383        public long getTotalTime(long batteryRealtime, int which) {
384            long val;
385            if (which == STATS_LAST) {
386                val = mLastTime;
387            } else {
388                val = computeRunTimeLocked(batteryRealtime);
389                if (which == STATS_UNPLUGGED) {
390                    val -= mUnpluggedTime;
391                } else if (which != STATS_TOTAL) {
392                    val -= mLoadedTime;
393                }
394            }
395
396            return val;
397        }
398
399        @Override
400        public int getCount(int which) {
401            int val;
402            if (which == STATS_LAST) {
403                val = mLastCount;
404            } else {
405                val = mCount;
406                if (which == STATS_UNPLUGGED) {
407                    val -= mUnpluggedCount;
408                } else if (which != STATS_TOTAL) {
409                    val -= mLoadedCount;
410                }
411            }
412
413            return val;
414        }
415
416        public void logState(Printer pw, String prefix) {
417            pw.println(prefix + "mNesting=" + mNesting + " mCount=" + mCount
418                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
419                    + " mUnpluggedCount=" + mUnpluggedCount);
420            pw.println(prefix + "mTotalTime=" + mTotalTime
421                    + " mLoadedTime=" + mLoadedTime);
422            pw.println(prefix + "mLastTime=" + mLastTime
423                    + " mUnpluggedTime=" + mUnpluggedTime);
424            pw.println(prefix + "mUpdateTime=" + mUpdateTime
425                    + " mAcquireTime=" + mAcquireTime);
426        }
427
428        void startRunningLocked(BatteryStatsImpl stats) {
429            if (mNesting++ == 0) {
430                mUpdateTime = stats.getBatteryRealtimeLocked(
431                        SystemClock.elapsedRealtime() * 1000);
432                if (mTimerPool != null) {
433                    // Accumulate time to all currently active timers before adding
434                    // this new one to the pool.
435                    refreshTimersLocked(stats, mTimerPool);
436                    // Add this timer to the active pool
437                    mTimerPool.add(this);
438                }
439                // Increment the count
440                mCount++;
441                mAcquireTime = mTotalTime;
442                if (DEBUG && mType < 0) {
443                    Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
444                            + " mTotalTime=" + mTotalTime + " mCount=" + mCount
445                            + " mAcquireTime=" + mAcquireTime);
446                }
447            }
448        }
449
450        void stopRunningLocked(BatteryStatsImpl stats) {
451            // Ignore attempt to stop a timer that isn't running
452            if (mNesting == 0) {
453                return;
454            }
455            if (--mNesting == 0) {
456                if (mTimerPool != null) {
457                    // Accumulate time to all active counters, scaled by the total
458                    // active in the pool, before taking this one out of the pool.
459                    refreshTimersLocked(stats, mTimerPool);
460                    // Remove this timer from the active pool
461                    mTimerPool.remove(this);
462                } else {
463                    final long realtime = SystemClock.elapsedRealtime() * 1000;
464                    final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
465                    mNesting = 1;
466                    mTotalTime = computeRunTimeLocked(batteryRealtime);
467                    mNesting = 0;
468                }
469
470                if (DEBUG && mType < 0) {
471                    Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
472                            + " mTotalTime=" + mTotalTime + " mCount=" + mCount
473                            + " mAcquireTime=" + mAcquireTime);
474                }
475
476                if (mTotalTime == mAcquireTime) {
477                    // If there was no change in the time, then discard this
478                    // count.  A somewhat cheezy strategy, but hey.
479                    mCount--;
480                }
481            }
482        }
483
484        // Update the total time for all other running Timers with the same type as this Timer
485        // due to a change in timer count
486        private static void refreshTimersLocked(final BatteryStatsImpl stats,
487                final ArrayList<Timer> pool) {
488            final long realtime = SystemClock.elapsedRealtime() * 1000;
489            final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
490            final int N = pool.size();
491            for (int i=N-1; i>= 0; i--) {
492                final Timer t = pool.get(i);
493                long heldTime = batteryRealtime - t.mUpdateTime;
494                if (heldTime > 0) {
495                    t.mTotalTime += heldTime / N;
496                }
497                t.mUpdateTime = batteryRealtime;
498            }
499        }
500
501        private long computeRunTimeLocked(long curBatteryRealtime) {
502            return mTotalTime + (mNesting > 0
503                    ? (curBatteryRealtime - mUpdateTime)
504                            / (mTimerPool != null ? mTimerPool.size() : 1)
505                    : 0);
506        }
507
508        void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
509            long runTime = computeRunTimeLocked(batteryRealtime);
510            // Divide by 1000 for backwards compatibility
511            out.writeLong((runTime + 500) / 1000);
512            out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
513            out.writeInt(mCount);
514            out.writeInt(mCount - mLoadedCount);
515        }
516
517        void readSummaryFromParcelLocked(Parcel in) {
518            // Multiply by 1000 for backwards compatibility
519            mTotalTime = mLoadedTime = in.readLong() * 1000;
520            mLastTime = in.readLong() * 1000;
521            mUnpluggedTime = mTotalTime;
522            mCount = mLoadedCount = in.readInt();
523            mLastCount = in.readInt();
524            mUnpluggedCount = mCount;
525            mNesting = 0;
526        }
527    }
528
529    public void doUnplug(long batteryUptime, long batteryRealtime) {
530        for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
531            Uid u = mUidStats.valueAt(iu);
532            u.mStartedTcpBytesReceived = NetStat.getUidRxBytes(u.mUid);
533            u.mStartedTcpBytesSent = NetStat.getUidTxBytes(u.mUid);
534            u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
535            u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
536        }
537        for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
538            mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
539        }
540    }
541
542    public void doPlug(long batteryUptime, long batteryRealtime) {
543        for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
544            Uid u = mUidStats.valueAt(iu);
545            if (u.mStartedTcpBytesReceived >= 0) {
546                u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
547                u.mStartedTcpBytesReceived = -1;
548            }
549            if (u.mStartedTcpBytesSent >= 0) {
550                u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
551                u.mStartedTcpBytesSent = -1;
552            }
553        }
554        for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
555            mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
556        }
557    }
558
559    public void noteStartGps(int uid) {
560        mUidStats.get(uid).noteStartGps();
561    }
562
563    public void noteStopGps(int uid) {
564        mUidStats.get(uid).noteStopGps();
565    }
566
567    public void noteScreenOnLocked() {
568        if (!mScreenOn) {
569            mScreenOn = true;
570            mScreenOnTimer.startRunningLocked(this);
571            if (mScreenBrightnessBin >= 0) {
572                mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this);
573            }
574        }
575    }
576
577    public void noteScreenOffLocked() {
578        if (mScreenOn) {
579            mScreenOn = false;
580            mScreenOnTimer.stopRunningLocked(this);
581            if (mScreenBrightnessBin >= 0) {
582                mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
583            }
584        }
585    }
586
587    public void noteScreenBrightnessLocked(int brightness) {
588        // Bin the brightness.
589        int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
590        if (bin < 0) bin = 0;
591        else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
592        if (mScreenBrightnessBin != bin) {
593            if (mScreenOn) {
594                if (mScreenBrightnessBin >= 0) {
595                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
596                }
597                mScreenBrightnessTimer[bin].startRunningLocked(this);
598            }
599            mScreenBrightnessBin = bin;
600        }
601    }
602
603    public void noteInputEventLocked() {
604        mInputEventCounter.stepLocked();
605    }
606
607    public void noteUserActivityLocked(int uid, int event) {
608        Uid u = mUidStats.get(uid);
609        if (u != null) {
610            u.noteUserActivityLocked(event);
611        }
612    }
613
614    public void notePhoneOnLocked() {
615        if (!mPhoneOn) {
616            mPhoneOn = true;
617            mPhoneOnTimer.startRunningLocked(this);
618        }
619    }
620
621    public void notePhoneOffLocked() {
622        if (mPhoneOn) {
623            mPhoneOn = false;
624            mPhoneOnTimer.stopRunningLocked(this);
625        }
626    }
627
628    public void notePhoneSignalStrengthLocked(int asu) {
629        // Bin the strength.
630        int bin;
631        if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
632        else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT;
633        else if (asu >= 8)  bin = SIGNAL_STRENGTH_GOOD;
634        else if (asu >= 4)  bin = SIGNAL_STRENGTH_MODERATE;
635        else bin = SIGNAL_STRENGTH_POOR;
636        if (mPhoneSignalStrengthBin != bin) {
637            if (mPhoneSignalStrengthBin >= 0) {
638                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this);
639            }
640            mPhoneSignalStrengthBin = bin;
641            mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
642        }
643    }
644
645    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
646        int bin = DATA_CONNECTION_NONE;
647        if (hasData) {
648            switch (dataType) {
649                case TelephonyManager.NETWORK_TYPE_EDGE:
650                    bin = DATA_CONNECTION_EDGE;
651                    break;
652                case TelephonyManager.NETWORK_TYPE_GPRS:
653                    bin = DATA_CONNECTION_GPRS;
654                    break;
655                case TelephonyManager.NETWORK_TYPE_UMTS:
656                    bin = DATA_CONNECTION_UMTS;
657                    break;
658                default:
659                    bin = DATA_CONNECTION_OTHER;
660                    break;
661            }
662        }
663        if (mPhoneDataConnectionType != bin) {
664            if (mPhoneDataConnectionType >= 0) {
665                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this);
666            }
667            mPhoneDataConnectionType = bin;
668            mPhoneDataConnectionsTimer[bin].startRunningLocked(this);
669        }
670    }
671
672    public void noteWifiOnLocked(int uid) {
673        if (!mWifiOn) {
674            mWifiOn = true;
675            mWifiOnTimer.startRunningLocked(this);
676        }
677        if (mWifiOnUid != uid) {
678            if (mWifiOnUid >= 0) {
679                Uid u = mUidStats.get(mWifiOnUid);
680                if (u != null) {
681                    u.noteWifiTurnedOffLocked();
682                }
683            }
684            mWifiOnUid = uid;
685            Uid u = mUidStats.get(uid);
686            if (u != null) {
687                u.noteWifiTurnedOnLocked();
688            }
689        }
690    }
691
692    public void noteWifiOffLocked(int uid) {
693        if (mWifiOn) {
694            mWifiOn = false;
695            mWifiOnTimer.stopRunningLocked(this);
696        }
697        if (mWifiOnUid >= 0) {
698            Uid u = mUidStats.get(mWifiOnUid);
699            if (u != null) {
700                u.noteWifiTurnedOffLocked();
701            }
702            mWifiOnUid = -1;
703        }
704    }
705
706    public void noteWifiRunningLocked() {
707        if (!mWifiRunning) {
708            mWifiRunning = true;
709            mWifiRunningTimer.startRunningLocked(this);
710        }
711    }
712
713    public void noteWifiStoppedLocked() {
714        if (mWifiRunning) {
715            mWifiRunning = false;
716            mWifiRunningTimer.stopRunningLocked(this);
717        }
718    }
719
720    public void noteBluetoothOnLocked() {
721        if (!mBluetoothOn) {
722            mBluetoothOn = true;
723            mBluetoothOnTimer.startRunningLocked(this);
724        }
725    }
726
727    public void noteBluetoothOffLocked() {
728        if (mBluetoothOn) {
729            mBluetoothOn = false;
730            mBluetoothOnTimer.stopRunningLocked(this);
731        }
732    }
733
734    public void noteFullWifiLockAcquiredLocked(int uid) {
735        Uid u = mUidStats.get(uid);
736        if (u != null) {
737            u.noteFullWifiLockAcquiredLocked();
738        }
739    }
740
741    public void noteFullWifiLockReleasedLocked(int uid) {
742        Uid u = mUidStats.get(uid);
743        if (u != null) {
744            u.noteFullWifiLockReleasedLocked();
745        }
746    }
747
748    public void noteScanWifiLockAcquiredLocked(int uid) {
749        Uid u = mUidStats.get(uid);
750        if (u != null) {
751            u.noteScanWifiLockAcquiredLocked();
752        }
753    }
754
755    public void noteScanWifiLockReleasedLocked(int uid) {
756        Uid u = mUidStats.get(uid);
757        if (u != null) {
758            u.noteScanWifiLockReleasedLocked();
759        }
760    }
761
762    @Override public long getScreenOnTime(long batteryRealtime, int which) {
763        return mScreenOnTimer.getTotalTime(batteryRealtime, which);
764    }
765
766    @Override public long getScreenBrightnessTime(int brightnessBin,
767            long batteryRealtime, int which) {
768        return mScreenBrightnessTimer[brightnessBin].getTotalTime(
769                batteryRealtime, which);
770    }
771
772    @Override public int getInputEventCount(int which) {
773        return mInputEventCounter.getCount(which);
774    }
775
776    @Override public long getPhoneOnTime(long batteryRealtime, int which) {
777        return mPhoneOnTimer.getTotalTime(batteryRealtime, which);
778    }
779
780    @Override public long getPhoneSignalStrengthTime(int strengthBin,
781            long batteryRealtime, int which) {
782        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTime(
783                batteryRealtime, which);
784    }
785
786    @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
787        return mPhoneDataConnectionsTimer[dataType].getCount(which);
788    }
789
790    @Override public long getPhoneDataConnectionTime(int dataType,
791            long batteryRealtime, int which) {
792        return mPhoneDataConnectionsTimer[dataType].getTotalTime(
793                batteryRealtime, which);
794    }
795
796    @Override public int getPhoneDataConnectionCount(int dataType, int which) {
797        return mPhoneDataConnectionsTimer[dataType].getCount(which);
798    }
799
800    @Override public long getWifiOnTime(long batteryRealtime, int which) {
801        return mWifiOnTimer.getTotalTime(batteryRealtime, which);
802    }
803
804    @Override public long getWifiRunningTime(long batteryRealtime, int which) {
805        return mWifiRunningTimer.getTotalTime(batteryRealtime, which);
806    }
807
808    @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
809        return mBluetoothOnTimer.getTotalTime(batteryRealtime, which);
810    }
811
812    @Override public boolean getIsOnBattery() {
813        return mOnBattery;
814    }
815
816    @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
817        return mUidStats;
818    }
819
820    /**
821     * The statistics associated with a particular uid.
822     */
823    public final class Uid extends BatteryStats.Uid {
824
825        final int mUid;
826        long mLoadedTcpBytesReceived;
827        long mLoadedTcpBytesSent;
828        long mCurrentTcpBytesReceived;
829        long mCurrentTcpBytesSent;
830        long mTcpBytesReceivedAtLastUnplug;
831        long mTcpBytesSentAtLastUnplug;
832
833        // These are not saved/restored when parcelling, since we want
834        // to return from the parcel with a snapshot of the state.
835        long mStartedTcpBytesReceived = -1;
836        long mStartedTcpBytesSent = -1;
837
838        boolean mWifiTurnedOn;
839        Timer mWifiTurnedOnTimer;
840
841        boolean mFullWifiLockOut;
842        Timer mFullWifiLockTimer;
843
844        boolean mScanWifiLockOut;
845        Timer mScanWifiLockTimer;
846
847        Counter[] mUserActivityCounters;
848
849        /**
850         * The statistics we have collected for this uid's wake locks.
851         */
852        final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>();
853
854        /**
855         * The statistics we have collected for this uid's sensor activations.
856         */
857        final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>();
858
859        /**
860         * The statistics we have collected for this uid's processes.
861         */
862        final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>();
863
864        /**
865         * The statistics we have collected for this uid's processes.
866         */
867        final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>();
868
869        public Uid(int uid) {
870            mUid = uid;
871            mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables);
872            mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables);
873            mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables);
874        }
875
876        @Override
877        public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
878            return mWakelockStats;
879        }
880
881        @Override
882        public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() {
883            return mSensorStats;
884        }
885
886        @Override
887        public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
888            return mProcessStats;
889        }
890
891        @Override
892        public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
893            return mPackageStats;
894        }
895
896        public int getUid() {
897            return mUid;
898        }
899
900        public long getTcpBytesReceived(int which) {
901            if (which == STATS_LAST) {
902                return mLoadedTcpBytesReceived;
903            } else {
904                long current = computeCurrentTcpBytesReceived();
905                if (which == STATS_UNPLUGGED) {
906                    current -= mTcpBytesReceivedAtLastUnplug;
907                } else if (which == STATS_TOTAL) {
908                    current += mLoadedTcpBytesReceived;
909                }
910                return current;
911            }
912        }
913
914        public long computeCurrentTcpBytesReceived() {
915            return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
916                    ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
917        }
918
919        public long getTcpBytesSent(int which) {
920            if (which == STATS_LAST) {
921                return mLoadedTcpBytesSent;
922            } else {
923                long current = computeCurrentTcpBytesSent();
924                if (which == STATS_UNPLUGGED) {
925                    current -= mTcpBytesSentAtLastUnplug;
926                } else if (which == STATS_TOTAL) {
927                    current += mLoadedTcpBytesSent;
928                }
929                return current;
930            }
931        }
932
933        @Override
934        public void noteWifiTurnedOnLocked() {
935            if (!mWifiTurnedOn) {
936                mWifiTurnedOn = true;
937                mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
938            }
939        }
940
941        @Override
942        public void noteWifiTurnedOffLocked() {
943            if (mWifiTurnedOn) {
944                mWifiTurnedOn = false;
945                mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
946            }
947        }
948
949        @Override
950        public void noteFullWifiLockAcquiredLocked() {
951            if (!mFullWifiLockOut) {
952                mFullWifiLockOut = true;
953                mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
954            }
955        }
956
957        @Override
958        public void noteFullWifiLockReleasedLocked() {
959            if (mFullWifiLockOut) {
960                mFullWifiLockOut = false;
961                mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
962            }
963        }
964
965        @Override
966        public void noteScanWifiLockAcquiredLocked() {
967            if (!mScanWifiLockOut) {
968                mScanWifiLockOut = true;
969                mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
970            }
971        }
972
973        @Override
974        public void noteScanWifiLockReleasedLocked() {
975            if (mScanWifiLockOut) {
976                mScanWifiLockOut = false;
977                mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
978            }
979        }
980
981        @Override
982        public long getWifiTurnedOnTime(long batteryRealtime, int which) {
983            return mWifiTurnedOnTimer.getTotalTime(batteryRealtime, which);
984        }
985
986        @Override
987        public long getFullWifiLockTime(long batteryRealtime, int which) {
988            return mFullWifiLockTimer.getTotalTime(batteryRealtime, which);
989        }
990
991        @Override
992        public long getScanWifiLockTime(long batteryRealtime, int which) {
993            return mScanWifiLockTimer.getTotalTime(batteryRealtime, which);
994        }
995
996        @Override
997        public void noteUserActivityLocked(int type) {
998            if (mUserActivityCounters == null) {
999                initUserActivityLocked();
1000            }
1001            if (type < 0) type = 0;
1002            else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1;
1003            mUserActivityCounters[type].stepLocked();
1004        }
1005
1006        @Override
1007        public boolean hasUserActivity() {
1008            return mUserActivityCounters != null;
1009        }
1010
1011        @Override
1012        public int getUserActivityCount(int type, int which) {
1013            if (mUserActivityCounters == null) {
1014                return 0;
1015            }
1016            return mUserActivityCounters[type].getCount(which);
1017        }
1018
1019        void initUserActivityLocked() {
1020            mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
1021            for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1022                mUserActivityCounters[i] = new Counter(mUnpluggables);
1023            }
1024        }
1025
1026        public long computeCurrentTcpBytesSent() {
1027            return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
1028                    ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
1029        }
1030
1031        void writeToParcelLocked(Parcel out, long batteryRealtime) {
1032            out.writeInt(mWakelockStats.size());
1033            for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
1034                out.writeString(wakelockEntry.getKey());
1035                Uid.Wakelock wakelock = wakelockEntry.getValue();
1036                wakelock.writeToParcelLocked(out, batteryRealtime);
1037            }
1038
1039            out.writeInt(mSensorStats.size());
1040            for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) {
1041                out.writeInt(sensorEntry.getKey());
1042                Uid.Sensor sensor = sensorEntry.getValue();
1043                sensor.writeToParcelLocked(out, batteryRealtime);
1044            }
1045
1046            out.writeInt(mProcessStats.size());
1047            for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) {
1048                out.writeString(procEntry.getKey());
1049                Uid.Proc proc = procEntry.getValue();
1050                proc.writeToParcelLocked(out);
1051            }
1052
1053            out.writeInt(mPackageStats.size());
1054            for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
1055                out.writeString(pkgEntry.getKey());
1056                Uid.Pkg pkg = pkgEntry.getValue();
1057                pkg.writeToParcelLocked(out);
1058            }
1059
1060            out.writeLong(mLoadedTcpBytesReceived);
1061            out.writeLong(mLoadedTcpBytesSent);
1062            out.writeLong(computeCurrentTcpBytesReceived());
1063            out.writeLong(computeCurrentTcpBytesSent());
1064            out.writeLong(mTcpBytesReceivedAtLastUnplug);
1065            out.writeLong(mTcpBytesSentAtLastUnplug);
1066            mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime);
1067            mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
1068            mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
1069            if (mUserActivityCounters == null) {
1070                out.writeInt(0);
1071            } else {
1072                out.writeInt(1);
1073                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1074                    mUserActivityCounters[i].writeToParcel(out);
1075                }
1076            }
1077        }
1078
1079        void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1080            int numWakelocks = in.readInt();
1081            mWakelockStats.clear();
1082            for (int j = 0; j < numWakelocks; j++) {
1083                String wakelockName = in.readString();
1084                Uid.Wakelock wakelock = new Wakelock();
1085                wakelock.readFromParcelLocked(unpluggables, in);
1086                mWakelockStats.put(wakelockName, wakelock);
1087            }
1088
1089            int numSensors = in.readInt();
1090            mSensorStats.clear();
1091            for (int k = 0; k < numSensors; k++) {
1092                int sensorNumber = in.readInt();
1093                Uid.Sensor sensor = new Sensor(sensorNumber);
1094                sensor.readFromParcelLocked(mUnpluggables, in);
1095                mSensorStats.put(sensorNumber, sensor);
1096            }
1097
1098            int numProcs = in.readInt();
1099            mProcessStats.clear();
1100            for (int k = 0; k < numProcs; k++) {
1101                String processName = in.readString();
1102                Uid.Proc proc = new Proc();
1103                proc.readFromParcelLocked(in);
1104                mProcessStats.put(processName, proc);
1105            }
1106
1107            int numPkgs = in.readInt();
1108            mPackageStats.clear();
1109            for (int l = 0; l < numPkgs; l++) {
1110                String packageName = in.readString();
1111                Uid.Pkg pkg = new Pkg();
1112                pkg.readFromParcelLocked(in);
1113                mPackageStats.put(packageName, pkg);
1114            }
1115
1116            mLoadedTcpBytesReceived = in.readLong();
1117            mLoadedTcpBytesSent = in.readLong();
1118            mCurrentTcpBytesReceived = in.readLong();
1119            mCurrentTcpBytesSent = in.readLong();
1120            mTcpBytesReceivedAtLastUnplug = in.readLong();
1121            mTcpBytesSentAtLastUnplug = in.readLong();
1122            mWifiTurnedOn = false;
1123            mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables, in);
1124            mFullWifiLockOut = false;
1125            mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in);
1126            mScanWifiLockOut = false;
1127            mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
1128            if (in.readInt() == 0) {
1129                mUserActivityCounters = null;
1130            } else {
1131                mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
1132                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
1133                    mUserActivityCounters[i] = new Counter(mUnpluggables, in);
1134                }
1135            }
1136        }
1137
1138        /**
1139         * The statistics associated with a particular wake lock.
1140         */
1141        public final class Wakelock extends BatteryStats.Uid.Wakelock {
1142            /**
1143             * How long (in ms) this uid has been keeping the device partially awake.
1144             */
1145            Timer mTimerPartial;
1146
1147            /**
1148             * How long (in ms) this uid has been keeping the device fully awake.
1149             */
1150            Timer mTimerFull;
1151
1152            /**
1153             * How long (in ms) this uid has had a window keeping the device awake.
1154             */
1155            Timer mTimerWindow;
1156
1157            /**
1158             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
1159             * proper timer pool from the given BatteryStatsImpl object.
1160             *
1161             * @param in the Parcel to be read from.
1162             * return a new Timer, or null.
1163             */
1164            private Timer readTimerFromParcel(int type, ArrayList<Timer> pool,
1165                    ArrayList<Unpluggable> unpluggables, Parcel in) {
1166                if (in.readInt() == 0) {
1167                    return null;
1168                }
1169
1170                return new Timer(type, pool, unpluggables, in);
1171            }
1172
1173            void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1174                mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
1175                        mPartialTimers, unpluggables, in);
1176                mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
1177                        mFullTimers, unpluggables, in);
1178                mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
1179                        mWindowTimers, unpluggables, in);
1180            }
1181
1182            void writeToParcelLocked(Parcel out, long batteryRealtime) {
1183                Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime);
1184                Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime);
1185                Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime);
1186            }
1187
1188            @Override
1189            public Timer getWakeTime(int type) {
1190                switch (type) {
1191                case WAKE_TYPE_FULL: return mTimerFull;
1192                case WAKE_TYPE_PARTIAL: return mTimerPartial;
1193                case WAKE_TYPE_WINDOW: return mTimerWindow;
1194                default: throw new IllegalArgumentException("type = " + type);
1195                }
1196            }
1197        }
1198
1199        public final class Sensor extends BatteryStats.Uid.Sensor {
1200            final int mHandle;
1201            Timer mTimer;
1202
1203            public Sensor(int handle) {
1204                mHandle = handle;
1205            }
1206
1207            private Timer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
1208                    Parcel in) {
1209                if (in.readInt() == 0) {
1210                    return null;
1211                }
1212
1213                ArrayList<Timer> pool = mSensorTimers.get(mHandle);
1214                if (pool == null) {
1215                    pool = new ArrayList<Timer>();
1216                    mSensorTimers.put(mHandle, pool);
1217                }
1218                return new Timer(0, pool, unpluggables, in);
1219            }
1220
1221            void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
1222                mTimer = readTimerFromParcel(unpluggables, in);
1223            }
1224
1225            void writeToParcelLocked(Parcel out, long batteryRealtime) {
1226                Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
1227            }
1228
1229            @Override
1230            public Timer getSensorTime() {
1231                return mTimer;
1232            }
1233
1234            public int getHandle() {
1235                return mHandle;
1236            }
1237        }
1238
1239        /**
1240         * The statistics associated with a particular process.
1241         */
1242        public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable {
1243            /**
1244             * Total time (in 1/100 sec) spent executing in user code.
1245             */
1246            long mUserTime;
1247
1248            /**
1249             * Total time (in 1/100 sec) spent executing in kernel code.
1250             */
1251            long mSystemTime;
1252
1253            /**
1254             * Number of times the process has been started.
1255             */
1256            int mStarts;
1257
1258            /**
1259             * The amount of user time loaded from a previous save.
1260             */
1261            long mLoadedUserTime;
1262
1263            /**
1264             * The amount of system time loaded from a previous save.
1265             */
1266            long mLoadedSystemTime;
1267
1268            /**
1269             * The number of times the process has started from a previous save.
1270             */
1271            int mLoadedStarts;
1272
1273            /**
1274             * The amount of user time loaded from the previous run.
1275             */
1276            long mLastUserTime;
1277
1278            /**
1279             * The amount of system time loaded from the previous run.
1280             */
1281            long mLastSystemTime;
1282
1283            /**
1284             * The number of times the process has started from the previous run.
1285             */
1286            int mLastStarts;
1287
1288            /**
1289             * The amount of user time when last unplugged.
1290             */
1291            long mUnpluggedUserTime;
1292
1293            /**
1294             * The amount of system time when last unplugged.
1295             */
1296            long mUnpluggedSystemTime;
1297
1298            /**
1299             * The number of times the process has started before unplugged.
1300             */
1301            int mUnpluggedStarts;
1302
1303            Proc() {
1304                mUnpluggables.add(this);
1305            }
1306
1307            public void unplug(long batteryUptime, long batteryRealtime) {
1308                mUnpluggedUserTime = mUserTime;
1309                mUnpluggedSystemTime = mSystemTime;
1310                mUnpluggedStarts = mStarts;
1311            }
1312
1313            public void plug(long batteryUptime, long batteryRealtime) {
1314            }
1315
1316            void writeToParcelLocked(Parcel out) {
1317                final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
1318                final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
1319
1320                out.writeLong(mUserTime);
1321                out.writeLong(mSystemTime);
1322                out.writeInt(mStarts);
1323                out.writeLong(mLoadedUserTime);
1324                out.writeLong(mLoadedSystemTime);
1325                out.writeInt(mLoadedStarts);
1326                out.writeLong(mLastUserTime);
1327                out.writeLong(mLastSystemTime);
1328                out.writeInt(mLastStarts);
1329                out.writeLong(mUnpluggedUserTime);
1330                out.writeLong(mUnpluggedSystemTime);
1331                out.writeInt(mUnpluggedStarts);
1332            }
1333
1334            void readFromParcelLocked(Parcel in) {
1335                mUserTime = in.readLong();
1336                mSystemTime = in.readLong();
1337                mStarts = in.readInt();
1338                mLoadedUserTime = in.readLong();
1339                mLoadedSystemTime = in.readLong();
1340                mLoadedStarts = in.readInt();
1341                mLastUserTime = in.readLong();
1342                mLastSystemTime = in.readLong();
1343                mLastStarts = in.readInt();
1344                mUnpluggedUserTime = in.readLong();
1345                mUnpluggedSystemTime = in.readLong();
1346                mUnpluggedStarts = in.readInt();
1347            }
1348
1349            public BatteryStatsImpl getBatteryStats() {
1350                return BatteryStatsImpl.this;
1351            }
1352
1353            public void addCpuTimeLocked(int utime, int stime) {
1354                mUserTime += utime;
1355                mSystemTime += stime;
1356            }
1357
1358            public void incStartsLocked() {
1359                mStarts++;
1360            }
1361
1362            @Override
1363            public long getUserTime(int which) {
1364                long val;
1365                if (which == STATS_LAST) {
1366                    val = mLastUserTime;
1367                } else {
1368                    val = mUserTime;
1369                    if (which == STATS_CURRENT) {
1370                        val -= mLoadedUserTime;
1371                    } else if (which == STATS_UNPLUGGED) {
1372                        val -= mUnpluggedUserTime;
1373                    }
1374                }
1375                return val;
1376            }
1377
1378            @Override
1379            public long getSystemTime(int which) {
1380                long val;
1381                if (which == STATS_LAST) {
1382                    val = mLastSystemTime;
1383                } else {
1384                    val = mSystemTime;
1385                    if (which == STATS_CURRENT) {
1386                        val -= mLoadedSystemTime;
1387                    } else if (which == STATS_UNPLUGGED) {
1388                        val -= mUnpluggedSystemTime;
1389                    }
1390                }
1391                return val;
1392            }
1393
1394            @Override
1395            public int getStarts(int which) {
1396                int val;
1397                if (which == STATS_LAST) {
1398                    val = mLastStarts;
1399                } else {
1400                    val = mStarts;
1401                    if (which == STATS_CURRENT) {
1402                        val -= mLoadedStarts;
1403                    } else if (which == STATS_UNPLUGGED) {
1404                        val -= mUnpluggedStarts;
1405                    }
1406                }
1407                return val;
1408            }
1409        }
1410
1411        /**
1412         * The statistics associated with a particular package.
1413         */
1414        public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable {
1415            /**
1416             * Number of times this package has done something that could wake up the
1417             * device from sleep.
1418             */
1419            int mWakeups;
1420
1421            /**
1422             * Number of things that could wake up the device loaded from a
1423             * previous save.
1424             */
1425            int mLoadedWakeups;
1426
1427            /**
1428             * Number of things that could wake up the device as of the
1429             * last run.
1430             */
1431            int mLastWakeups;
1432
1433            /**
1434             * Number of things that could wake up the device as of the
1435             * last run.
1436             */
1437            int mUnpluggedWakeups;
1438
1439            /**
1440             * The statics we have collected for this package's services.
1441             */
1442            final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
1443
1444            Pkg() {
1445                mUnpluggables.add(this);
1446            }
1447
1448            public void unplug(long batteryUptime, long batteryRealtime) {
1449                mUnpluggedWakeups = mWakeups;
1450            }
1451
1452            public void plug(long batteryUptime, long batteryRealtime) {
1453            }
1454
1455            void readFromParcelLocked(Parcel in) {
1456                mWakeups = in.readInt();
1457                mLoadedWakeups = in.readInt();
1458                mLastWakeups = in.readInt();
1459                mUnpluggedWakeups = in.readInt();
1460
1461                int numServs = in.readInt();
1462                mServiceStats.clear();
1463                for (int m = 0; m < numServs; m++) {
1464                    String serviceName = in.readString();
1465                    Uid.Pkg.Serv serv = new Serv();
1466                    mServiceStats.put(serviceName, serv);
1467
1468                    serv.readFromParcelLocked(in);
1469                }
1470            }
1471
1472            void writeToParcelLocked(Parcel out) {
1473                out.writeInt(mWakeups);
1474                out.writeInt(mLoadedWakeups);
1475                out.writeInt(mLastWakeups);
1476                out.writeInt(mUnpluggedWakeups);
1477
1478                out.writeInt(mServiceStats.size());
1479                for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
1480                    out.writeString(servEntry.getKey());
1481                    Uid.Pkg.Serv serv = servEntry.getValue();
1482
1483                    serv.writeToParcelLocked(out);
1484                }
1485            }
1486
1487            @Override
1488            public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
1489                return mServiceStats;
1490            }
1491
1492            @Override
1493            public int getWakeups(int which) {
1494                int val;
1495                if (which == STATS_LAST) {
1496                    val = mLastWakeups;
1497                } else {
1498                    val = mWakeups;
1499                    if (which == STATS_CURRENT) {
1500                        val -= mLoadedWakeups;
1501                    } else if (which == STATS_UNPLUGGED) {
1502                        val -= mUnpluggedWakeups;
1503                    }
1504                }
1505
1506                return val;
1507            }
1508
1509            /**
1510             * The statistics associated with a particular service.
1511             */
1512            public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable {
1513                /**
1514                 * Total time (ms in battery uptime) the service has been left started.
1515                 */
1516                long mStartTime;
1517
1518                /**
1519                 * If service has been started and not yet stopped, this is
1520                 * when it was started.
1521                 */
1522                long mRunningSince;
1523
1524                /**
1525                 * True if we are currently running.
1526                 */
1527                boolean mRunning;
1528
1529                /**
1530                 * Total number of times startService() has been called.
1531                 */
1532                int mStarts;
1533
1534                /**
1535                 * Total time (ms in battery uptime) the service has been left launched.
1536                 */
1537                long mLaunchedTime;
1538
1539                /**
1540                 * If service has been launched and not yet exited, this is
1541                 * when it was launched (ms in battery uptime).
1542                 */
1543                long mLaunchedSince;
1544
1545                /**
1546                 * True if we are currently launched.
1547                 */
1548                boolean mLaunched;
1549
1550                /**
1551                 * Total number times the service has been launched.
1552                 */
1553                int mLaunches;
1554
1555                /**
1556                 * The amount of time spent started loaded from a previous save
1557                 * (ms in battery uptime).
1558                 */
1559                long mLoadedStartTime;
1560
1561                /**
1562                 * The number of starts loaded from a previous save.
1563                 */
1564                int mLoadedStarts;
1565
1566                /**
1567                 * The number of launches loaded from a previous save.
1568                 */
1569                int mLoadedLaunches;
1570
1571                /**
1572                 * The amount of time spent started as of the last run (ms
1573                 * in battery uptime).
1574                 */
1575                long mLastStartTime;
1576
1577                /**
1578                 * The number of starts as of the last run.
1579                 */
1580                int mLastStarts;
1581
1582                /**
1583                 * The number of launches as of the last run.
1584                 */
1585                int mLastLaunches;
1586
1587                /**
1588                 * The amount of time spent started when last unplugged (ms
1589                 * in battery uptime).
1590                 */
1591                long mUnpluggedStartTime;
1592
1593                /**
1594                 * The number of starts when last unplugged.
1595                 */
1596                int mUnpluggedStarts;
1597
1598                /**
1599                 * The number of launches when last unplugged.
1600                 */
1601                int mUnpluggedLaunches;
1602
1603                Serv() {
1604                    mUnpluggables.add(this);
1605                }
1606
1607                public void unplug(long batteryUptime, long batteryRealtime) {
1608                    mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
1609                    mUnpluggedStarts = mStarts;
1610                    mUnpluggedLaunches = mLaunches;
1611                }
1612
1613                public void plug(long batteryUptime, long batteryRealtime) {
1614                }
1615
1616                void readFromParcelLocked(Parcel in) {
1617                    mStartTime = in.readLong();
1618                    mRunningSince = in.readLong();
1619                    mRunning = in.readInt() != 0;
1620                    mStarts = in.readInt();
1621                    mLaunchedTime = in.readLong();
1622                    mLaunchedSince = in.readLong();
1623                    mLaunched = in.readInt() != 0;
1624                    mLaunches = in.readInt();
1625                    mLoadedStartTime = in.readLong();
1626                    mLoadedStarts = in.readInt();
1627                    mLoadedLaunches = in.readInt();
1628                    mLastStartTime = in.readLong();
1629                    mLastStarts = in.readInt();
1630                    mLastLaunches = in.readInt();
1631                    mUnpluggedStartTime = in.readLong();
1632                    mUnpluggedStarts = in.readInt();
1633                    mUnpluggedLaunches = in.readInt();
1634                }
1635
1636                void writeToParcelLocked(Parcel out) {
1637                    out.writeLong(mStartTime);
1638                    out.writeLong(mRunningSince);
1639                    out.writeInt(mRunning ? 1 : 0);
1640                    out.writeInt(mStarts);
1641                    out.writeLong(mLaunchedTime);
1642                    out.writeLong(mLaunchedSince);
1643                    out.writeInt(mLaunched ? 1 : 0);
1644                    out.writeInt(mLaunches);
1645                    out.writeLong(mLoadedStartTime);
1646                    out.writeInt(mLoadedStarts);
1647                    out.writeInt(mLoadedLaunches);
1648                    out.writeLong(mLastStartTime);
1649                    out.writeInt(mLastStarts);
1650                    out.writeInt(mLastLaunches);
1651                    out.writeLong(mUnpluggedStartTime);
1652                    out.writeInt(mUnpluggedStarts);
1653                    out.writeInt(mUnpluggedLaunches);
1654                }
1655
1656                long getLaunchTimeToNowLocked(long batteryUptime) {
1657                    if (!mLaunched) return mLaunchedTime;
1658                    return mLaunchedTime + batteryUptime - mLaunchedSince;
1659                }
1660
1661                long getStartTimeToNowLocked(long batteryUptime) {
1662                    if (!mRunning) return mStartTime;
1663                    return mStartTime + batteryUptime - mRunningSince;
1664                }
1665
1666                public void startLaunchedLocked() {
1667                    if (!mLaunched) {
1668                        mLaunches++;
1669                        mLaunchedSince = getBatteryUptimeLocked();
1670                        mLaunched = true;
1671                    }
1672                }
1673
1674                public void stopLaunchedLocked() {
1675                    if (mLaunched) {
1676                        long time = getBatteryUptimeLocked() - mLaunchedSince;
1677                        if (time > 0) {
1678                            mLaunchedTime += time;
1679                        } else {
1680                            mLaunches--;
1681                        }
1682                        mLaunched = false;
1683                    }
1684                }
1685
1686                public void startRunningLocked() {
1687                    if (!mRunning) {
1688                        mStarts++;
1689                        mRunningSince = getBatteryUptimeLocked();
1690                        mRunning = true;
1691                    }
1692                }
1693
1694                public void stopRunningLocked() {
1695                    if (mRunning) {
1696                        long time = getBatteryUptimeLocked() - mRunningSince;
1697                        if (time > 0) {
1698                            mStartTime += time;
1699                        } else {
1700                            mStarts--;
1701                        }
1702                        mRunning = false;
1703                    }
1704                }
1705
1706                public BatteryStatsImpl getBatteryStats() {
1707                    return BatteryStatsImpl.this;
1708                }
1709
1710                @Override
1711                public int getLaunches(int which) {
1712                    int val;
1713
1714                    if (which == STATS_LAST) {
1715                        val = mLastLaunches;
1716                    } else {
1717                        val = mLaunches;
1718                        if (which == STATS_CURRENT) {
1719                            val -= mLoadedLaunches;
1720                        } else if (which == STATS_UNPLUGGED) {
1721                            val -= mUnpluggedLaunches;
1722                        }
1723                    }
1724
1725                    return val;
1726                }
1727
1728                @Override
1729                public long getStartTime(long now, int which) {
1730                    long val;
1731                    if (which == STATS_LAST) {
1732                        val = mLastStartTime;
1733                    } else {
1734                        val = getStartTimeToNowLocked(now);
1735                        if (which == STATS_CURRENT) {
1736                            val -= mLoadedStartTime;
1737                        } else if (which == STATS_UNPLUGGED) {
1738                            val -= mUnpluggedStartTime;
1739                        }
1740                    }
1741
1742                    return val;
1743                }
1744
1745                @Override
1746                public int getStarts(int which) {
1747                    int val;
1748                    if (which == STATS_LAST) {
1749                        val = mLastStarts;
1750                    } else {
1751                        val = mStarts;
1752                        if (which == STATS_CURRENT) {
1753                            val -= mLoadedStarts;
1754                        } else if (which == STATS_UNPLUGGED) {
1755                            val -= mUnpluggedStarts;
1756                        }
1757                    }
1758
1759                    return val;
1760                }
1761            }
1762
1763            public BatteryStatsImpl getBatteryStats() {
1764                return BatteryStatsImpl.this;
1765            }
1766
1767            public void incWakeupsLocked() {
1768                mWakeups++;
1769            }
1770
1771            final Serv newServiceStatsLocked() {
1772                return new Serv();
1773            }
1774        }
1775
1776        /**
1777         * Retrieve the statistics object for a particular process, creating
1778         * if needed.
1779         */
1780        public Proc getProcessStatsLocked(String name) {
1781            Proc ps = mProcessStats.get(name);
1782            if (ps == null) {
1783                ps = new Proc();
1784                mProcessStats.put(name, ps);
1785            }
1786
1787            return ps;
1788        }
1789
1790        /**
1791         * Retrieve the statistics object for a particular service, creating
1792         * if needed.
1793         */
1794        public Pkg getPackageStatsLocked(String name) {
1795            Pkg ps = mPackageStats.get(name);
1796            if (ps == null) {
1797                ps = new Pkg();
1798                mPackageStats.put(name, ps);
1799            }
1800
1801            return ps;
1802        }
1803
1804        /**
1805         * Retrieve the statistics object for a particular service, creating
1806         * if needed.
1807         */
1808        public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
1809            Pkg ps = getPackageStatsLocked(pkg);
1810            Pkg.Serv ss = ps.mServiceStats.get(serv);
1811            if (ss == null) {
1812                ss = ps.newServiceStatsLocked();
1813                ps.mServiceStats.put(serv, ss);
1814            }
1815
1816            return ss;
1817        }
1818
1819        public Timer getWakeTimerLocked(String name, int type) {
1820            Wakelock wl = mWakelockStats.get(name);
1821            if (wl == null) {
1822                wl = new Wakelock();
1823                mWakelockStats.put(name, wl);
1824            }
1825            Timer t = null;
1826            switch (type) {
1827                case WAKE_TYPE_PARTIAL:
1828                    t = wl.mTimerPartial;
1829                    if (t == null) {
1830                        t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
1831                        wl.mTimerPartial = t;
1832                    }
1833                    return t;
1834                case WAKE_TYPE_FULL:
1835                    t = wl.mTimerFull;
1836                    if (t == null) {
1837                        t = new Timer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
1838                        wl.mTimerFull = t;
1839                    }
1840                    return t;
1841                case WAKE_TYPE_WINDOW:
1842                    t = wl.mTimerWindow;
1843                    if (t == null) {
1844                        t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
1845                        wl.mTimerWindow = t;
1846                    }
1847                    return t;
1848                default:
1849                    throw new IllegalArgumentException("type=" + type);
1850            }
1851        }
1852
1853        public Timer getSensorTimerLocked(int sensor, boolean create) {
1854            Sensor se = mSensorStats.get(sensor);
1855            if (se == null) {
1856                if (!create) {
1857                    return null;
1858                }
1859                se = new Sensor(sensor);
1860                mSensorStats.put(sensor, se);
1861            }
1862            Timer t = se.mTimer;
1863            if (t != null) {
1864                return t;
1865            }
1866            ArrayList<Timer> timers = mSensorTimers.get(sensor);
1867            if (timers == null) {
1868                timers = new ArrayList<Timer>();
1869                mSensorTimers.put(sensor, timers);
1870            }
1871            t = new Timer(BatteryStats.SENSOR, timers, mUnpluggables);
1872            se.mTimer = t;
1873            return t;
1874        }
1875
1876        public void noteStartWakeLocked(String name, int type) {
1877            Timer t = getWakeTimerLocked(name, type);
1878            if (t != null) {
1879                t.startRunningLocked(BatteryStatsImpl.this);
1880            }
1881        }
1882
1883        public void noteStopWakeLocked(String name, int type) {
1884            Timer t = getWakeTimerLocked(name, type);
1885            if (t != null) {
1886                t.stopRunningLocked(BatteryStatsImpl.this);
1887            }
1888        }
1889
1890        public void noteStartSensor(int sensor) {
1891            Timer t = getSensorTimerLocked(sensor, true);
1892            if (t != null) {
1893                t.startRunningLocked(BatteryStatsImpl.this);
1894            }
1895        }
1896
1897        public void noteStopSensor(int sensor) {
1898            // Don't create a timer if one doesn't already exist
1899            Timer t = getSensorTimerLocked(sensor, false);
1900            if (t != null) {
1901                t.stopRunningLocked(BatteryStatsImpl.this);
1902            }
1903        }
1904
1905        public void noteStartGps() {
1906            Timer t = getSensorTimerLocked(Sensor.GPS, true);
1907            if (t != null) {
1908                t.startRunningLocked(BatteryStatsImpl.this);
1909            }
1910        }
1911
1912        public void noteStopGps() {
1913            Timer t = getSensorTimerLocked(Sensor.GPS, false);
1914            if (t != null) {
1915                t.stopRunningLocked(BatteryStatsImpl.this);
1916            }
1917        }
1918
1919        public BatteryStatsImpl getBatteryStats() {
1920            return BatteryStatsImpl.this;
1921        }
1922    }
1923
1924    public BatteryStatsImpl(String filename) {
1925        mFile = new File(filename);
1926        mBackupFile = new File(filename + ".bak");
1927        mStartCount++;
1928        mScreenOnTimer = new Timer(-1, null, mUnpluggables);
1929        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
1930            mScreenBrightnessTimer[i] = new Timer(-100-i, null, mUnpluggables);
1931        }
1932        mInputEventCounter = new Counter(mUnpluggables);
1933        mPhoneOnTimer = new Timer(-2, null, mUnpluggables);
1934        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
1935            mPhoneSignalStrengthsTimer[i] = new Timer(-200-i, null, mUnpluggables);
1936        }
1937        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
1938            mPhoneDataConnectionsTimer[i] = new Timer(-300-i, null, mUnpluggables);
1939        }
1940        mWifiOnTimer = new Timer(-3, null, mUnpluggables);
1941        mWifiRunningTimer = new Timer(-4, null, mUnpluggables);
1942        mBluetoothOnTimer = new Timer(-5, null, mUnpluggables);
1943        mOnBattery = mOnBatteryInternal = false;
1944        mTrackBatteryPastUptime = 0;
1945        mTrackBatteryPastRealtime = 0;
1946        mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
1947        mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
1948        mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
1949        mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
1950        mUnpluggedStartLevel = 0;
1951        mPluggedStartLevel = 0;
1952    }
1953
1954    public BatteryStatsImpl(Parcel p) {
1955        mFile = mBackupFile = null;
1956        readFromParcel(p);
1957    }
1958
1959    @Override
1960    public int getStartCount() {
1961        return mStartCount;
1962    }
1963
1964    public boolean isOnBattery() {
1965        return mOnBattery;
1966    }
1967
1968    public void setOnBattery(boolean onBattery, int level) {
1969        synchronized(this) {
1970            if (mOnBattery != onBattery) {
1971                mOnBattery = mOnBatteryInternal = onBattery;
1972
1973                long uptime = SystemClock.uptimeMillis() * 1000;
1974                long mSecRealtime = SystemClock.elapsedRealtime();
1975                long realtime = mSecRealtime * 1000;
1976                if (onBattery) {
1977                    mTrackBatteryUptimeStart = uptime;
1978                    mTrackBatteryRealtimeStart = realtime;
1979                    mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
1980                    mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
1981                    mUnpluggedStartLevel = level;
1982                    doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
1983                } else {
1984                    mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
1985                    mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
1986                    mPluggedStartLevel = level;
1987                    doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
1988                }
1989                if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
1990                    if (mFile != null) {
1991                        writeLocked();
1992                    }
1993                }
1994            }
1995        }
1996    }
1997
1998    public long getAwakeTimeBattery() {
1999        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
2000    }
2001
2002    public long getAwakeTimePlugged() {
2003        return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
2004    }
2005
2006    @Override
2007    public long computeUptime(long curTime, int which) {
2008        switch (which) {
2009            case STATS_TOTAL: return mUptime + (curTime-mUptimeStart);
2010            case STATS_LAST: return mLastUptime;
2011            case STATS_CURRENT: return (curTime-mUptimeStart);
2012            case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
2013        }
2014        return 0;
2015    }
2016
2017    @Override
2018    public long computeRealtime(long curTime, int which) {
2019        switch (which) {
2020            case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart);
2021            case STATS_LAST: return mLastRealtime;
2022            case STATS_CURRENT: return (curTime-mRealtimeStart);
2023            case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
2024        }
2025        return 0;
2026    }
2027
2028    @Override
2029    public long computeBatteryUptime(long curTime, int which) {
2030        switch (which) {
2031            case STATS_TOTAL:
2032                return mBatteryUptime + getBatteryUptime(curTime);
2033            case STATS_LAST:
2034                return mBatteryLastUptime;
2035            case STATS_CURRENT:
2036                return getBatteryUptime(curTime);
2037            case STATS_UNPLUGGED:
2038                return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
2039        }
2040        return 0;
2041    }
2042
2043    @Override
2044    public long computeBatteryRealtime(long curTime, int which) {
2045        switch (which) {
2046            case STATS_TOTAL:
2047                return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
2048            case STATS_LAST:
2049                return mBatteryLastRealtime;
2050            case STATS_CURRENT:
2051                return getBatteryRealtimeLocked(curTime);
2052            case STATS_UNPLUGGED:
2053                return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
2054        }
2055        return 0;
2056    }
2057
2058    long getBatteryUptimeLocked(long curTime) {
2059        long time = mTrackBatteryPastUptime;
2060        if (mOnBatteryInternal) {
2061            time += curTime - mTrackBatteryUptimeStart;
2062        }
2063        return time;
2064    }
2065
2066    long getBatteryUptimeLocked() {
2067        return getBatteryUptime(SystemClock.uptimeMillis() * 1000);
2068    }
2069
2070    @Override
2071    public long getBatteryUptime(long curTime) {
2072        return getBatteryUptimeLocked(curTime);
2073    }
2074
2075    long getBatteryRealtimeLocked(long curTime) {
2076        long time = mTrackBatteryPastRealtime;
2077        if (mOnBatteryInternal) {
2078            time += curTime - mTrackBatteryRealtimeStart;
2079        }
2080        return time;
2081    }
2082
2083    @Override
2084    public long getBatteryRealtime(long curTime) {
2085        return getBatteryRealtimeLocked(curTime);
2086    }
2087
2088    @Override
2089    public int getUnpluggedStartLevel() {
2090        synchronized(this) {
2091            return getUnluggedStartLevelLocked();
2092        }
2093    }
2094
2095    public int getUnluggedStartLevelLocked() {
2096            return mUnpluggedStartLevel;
2097    }
2098
2099    @Override
2100    public int getPluggedStartLevel() {
2101        synchronized(this) {
2102            return getPluggedStartLevelLocked();
2103        }
2104    }
2105
2106    public int getPluggedStartLevelLocked() {
2107            return mPluggedStartLevel;
2108    }
2109
2110    /**
2111     * Retrieve the statistics object for a particular uid, creating if needed.
2112     */
2113    public Uid getUidStatsLocked(int uid) {
2114        Uid u = mUidStats.get(uid);
2115        if (u == null) {
2116            u = new Uid(uid);
2117            mUidStats.put(uid, u);
2118        }
2119        return u;
2120    }
2121
2122    /**
2123     * Remove the statistics object for a particular uid.
2124     */
2125    public void removeUidStatsLocked(int uid) {
2126        mUidStats.remove(uid);
2127    }
2128
2129    /**
2130     * Retrieve the statistics object for a particular process, creating
2131     * if needed.
2132     */
2133    public Uid.Proc getProcessStatsLocked(int uid, String name) {
2134        Uid u = getUidStatsLocked(uid);
2135        return u.getProcessStatsLocked(name);
2136    }
2137
2138    /**
2139     * Retrieve the statistics object for a particular process, creating
2140     * if needed.
2141     */
2142    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
2143        Uid u = getUidStatsLocked(uid);
2144        return u.getPackageStatsLocked(pkg);
2145    }
2146
2147    /**
2148     * Retrieve the statistics object for a particular service, creating
2149     * if needed.
2150     */
2151    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
2152        Uid u = getUidStatsLocked(uid);
2153        return u.getServiceStatsLocked(pkg, name);
2154    }
2155
2156    public void writeLocked() {
2157        if ((mFile == null) || (mBackupFile == null)) {
2158            Log.w("BatteryStats", "writeLocked: no file associated with this instance");
2159            return;
2160        }
2161
2162        // Keep the old file around until we know the new one has
2163        // been successfully written.
2164        if (mFile.exists()) {
2165            if (mBackupFile.exists()) {
2166                mBackupFile.delete();
2167            }
2168            mFile.renameTo(mBackupFile);
2169        }
2170
2171        try {
2172            FileOutputStream stream = new FileOutputStream(mFile);
2173            Parcel out = Parcel.obtain();
2174            writeSummaryToParcel(out);
2175            stream.write(out.marshall());
2176            out.recycle();
2177
2178            stream.flush();
2179            stream.close();
2180            mBackupFile.delete();
2181
2182            mLastWriteTime = SystemClock.elapsedRealtime();
2183        } catch (IOException e) {
2184            Log.e("BatteryStats", "Error writing battery statistics", e);
2185        }
2186    }
2187
2188    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
2189        int pos = 0;
2190        int avail = stream.available();
2191        byte[] data = new byte[avail];
2192        while (true) {
2193            int amt = stream.read(data, pos, data.length-pos);
2194            //Log.i("foo", "Read " + amt + " bytes at " + pos
2195            //        + " of avail " + data.length);
2196            if (amt <= 0) {
2197                //Log.i("foo", "**** FINISHED READING: pos=" + pos
2198                //        + " len=" + data.length);
2199                return data;
2200            }
2201            pos += amt;
2202            avail = stream.available();
2203            if (avail > data.length-pos) {
2204                byte[] newData = new byte[pos+avail];
2205                System.arraycopy(data, 0, newData, 0, pos);
2206                data = newData;
2207            }
2208        }
2209    }
2210
2211    public void readLocked() {
2212        if ((mFile == null) || (mBackupFile == null)) {
2213            Log.w("BatteryStats", "readLocked: no file associated with this instance");
2214            return;
2215        }
2216
2217        mUidStats.clear();
2218
2219        FileInputStream stream = null;
2220        if (mBackupFile.exists()) {
2221            try {
2222                stream = new FileInputStream(mBackupFile);
2223            } catch (java.io.IOException e) {
2224                // We'll try for the normal settings file.
2225            }
2226        }
2227
2228        try {
2229            if (stream == null) {
2230                if (!mFile.exists()) {
2231                    return;
2232                }
2233                stream = new FileInputStream(mFile);
2234            }
2235
2236            byte[] raw = readFully(stream);
2237            Parcel in = Parcel.obtain();
2238            in.unmarshall(raw, 0, raw.length);
2239            in.setDataPosition(0);
2240            stream.close();
2241
2242            readSummaryFromParcel(in);
2243        } catch(java.io.IOException e) {
2244            Log.e("BatteryStats", "Error reading battery statistics", e);
2245        }
2246    }
2247
2248    public int describeContents() {
2249        return 0;
2250    }
2251
2252    private void readSummaryFromParcel(Parcel in) {
2253        final int version = in.readInt();
2254        if (version != VERSION) {
2255            Log.w("BatteryStats", "readFromParcel: version got " + version
2256                + ", expected " + VERSION + "; erasing old stats");
2257            return;
2258        }
2259
2260        mStartCount = in.readInt();
2261        mBatteryUptime = in.readLong();
2262        mBatteryLastUptime = in.readLong();
2263        mBatteryRealtime = in.readLong();
2264        mBatteryLastRealtime = in.readLong();
2265        mUptime = in.readLong();
2266        mLastUptime = in.readLong();
2267        mRealtime = in.readLong();
2268        mLastRealtime = in.readLong();
2269        mUnpluggedStartLevel = in.readInt();
2270        mPluggedStartLevel = in.readInt();
2271
2272        mStartCount++;
2273
2274        mScreenOn = false;
2275        mScreenOnTimer.readSummaryFromParcelLocked(in);
2276        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2277            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
2278        }
2279        mInputEventCounter.readSummaryFromParcelLocked(in);
2280        mPhoneOn = false;
2281        mPhoneOnTimer.readSummaryFromParcelLocked(in);
2282        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2283            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
2284        }
2285        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2286            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
2287        }
2288        mWifiOn = false;
2289        mWifiOnTimer.readSummaryFromParcelLocked(in);
2290        mWifiRunning = false;
2291        mWifiRunningTimer.readSummaryFromParcelLocked(in);
2292        mBluetoothOn = false;
2293        mBluetoothOnTimer.readSummaryFromParcelLocked(in);
2294
2295        final int NU = in.readInt();
2296        for (int iu = 0; iu < NU; iu++) {
2297            int uid = in.readInt();
2298            Uid u = new Uid(uid);
2299            mUidStats.put(uid, u);
2300
2301            u.mWifiTurnedOn = false;
2302            u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in);
2303            u.mFullWifiLockOut = false;
2304            u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
2305            u.mScanWifiLockOut = false;
2306            u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
2307
2308            if (in.readInt() != 0) {
2309                if (u.mUserActivityCounters == null) {
2310                    u.initUserActivityLocked();
2311                }
2312                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2313                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
2314                }
2315            }
2316
2317            int NW = in.readInt();
2318            for (int iw = 0; iw < NW; iw++) {
2319                String wlName = in.readString();
2320                if (in.readInt() != 0) {
2321                    u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
2322                }
2323                if (in.readInt() != 0) {
2324                    u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
2325                }
2326                if (in.readInt() != 0) {
2327                    u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
2328                }
2329            }
2330
2331            int NP = in.readInt();
2332            for (int is = 0; is < NP; is++) {
2333                int seNumber = in.readInt();
2334                if (in.readInt() != 0) {
2335                    u.getSensorTimerLocked(seNumber, true)
2336                            .readSummaryFromParcelLocked(in);
2337                }
2338            }
2339
2340            NP = in.readInt();
2341            for (int ip = 0; ip < NP; ip++) {
2342                String procName = in.readString();
2343                Uid.Proc p = u.getProcessStatsLocked(procName);
2344                p.mUserTime = p.mLoadedUserTime = in.readLong();
2345                p.mLastUserTime = in.readLong();
2346                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
2347                p.mLastSystemTime = in.readLong();
2348                p.mStarts = p.mLoadedStarts = in.readInt();
2349                p.mLastStarts = in.readInt();
2350            }
2351
2352            NP = in.readInt();
2353            for (int ip = 0; ip < NP; ip++) {
2354                String pkgName = in.readString();
2355                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
2356                p.mWakeups = p.mLoadedWakeups = in.readInt();
2357                p.mLastWakeups = in.readInt();
2358                final int NS = in.readInt();
2359                for (int is = 0; is < NS; is++) {
2360                    String servName = in.readString();
2361                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
2362                    s.mStartTime = s.mLoadedStartTime = in.readLong();
2363                    s.mLastStartTime = in.readLong();
2364                    s.mStarts = s.mLoadedStarts = in.readInt();
2365                    s.mLastStarts = in.readInt();
2366                    s.mLaunches = s.mLoadedLaunches = in.readInt();
2367                    s.mLastLaunches = in.readInt();
2368                }
2369            }
2370
2371            u.mLoadedTcpBytesReceived = in.readLong();
2372            u.mLoadedTcpBytesSent = in.readLong();
2373        }
2374    }
2375
2376    /**
2377     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
2378     * disk.  This format does not allow a lossless round-trip.
2379     *
2380     * @param out the Parcel to be written to.
2381     */
2382    public void writeSummaryToParcel(Parcel out) {
2383        final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
2384        final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
2385        final long NOW = getBatteryUptimeLocked(NOW_SYS);
2386        final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS);
2387
2388        out.writeInt(VERSION);
2389
2390        out.writeInt(mStartCount);
2391        out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL));
2392        out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT));
2393        out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL));
2394        out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT));
2395        out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL));
2396        out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT));
2397        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL));
2398        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT));
2399        out.writeInt(mUnpluggedStartLevel);
2400        out.writeInt(mPluggedStartLevel);
2401
2402
2403        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2404        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2405            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
2406        }
2407        mInputEventCounter.writeSummaryFromParcelLocked(out);
2408        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2409        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2410            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
2411        }
2412        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2413            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
2414        }
2415        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2416        mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2417        mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2418
2419        final int NU = mUidStats.size();
2420        out.writeInt(NU);
2421        for (int iu = 0; iu < NU; iu++) {
2422            out.writeInt(mUidStats.keyAt(iu));
2423            Uid u = mUidStats.valueAt(iu);
2424
2425            u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2426            u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2427            u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2428
2429            if (u.mUserActivityCounters == null) {
2430                out.writeInt(0);
2431            } else {
2432                out.writeInt(1);
2433                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
2434                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
2435                }
2436            }
2437
2438            int NW = u.mWakelockStats.size();
2439            out.writeInt(NW);
2440            if (NW > 0) {
2441                for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent
2442                        : u.mWakelockStats.entrySet()) {
2443                    out.writeString(ent.getKey());
2444                    Uid.Wakelock wl = ent.getValue();
2445                    if (wl.mTimerFull != null) {
2446                        out.writeInt(1);
2447                        wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL);
2448                    } else {
2449                        out.writeInt(0);
2450                    }
2451                    if (wl.mTimerPartial != null) {
2452                        out.writeInt(1);
2453                        wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL);
2454                    } else {
2455                        out.writeInt(0);
2456                    }
2457                    if (wl.mTimerWindow != null) {
2458                        out.writeInt(1);
2459                        wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL);
2460                    } else {
2461                        out.writeInt(0);
2462                    }
2463                }
2464            }
2465
2466            int NSE = u.mSensorStats.size();
2467            out.writeInt(NSE);
2468            if (NSE > 0) {
2469                for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent
2470                        : u.mSensorStats.entrySet()) {
2471                    out.writeInt(ent.getKey());
2472                    Uid.Sensor se = ent.getValue();
2473                    if (se.mTimer != null) {
2474                        out.writeInt(1);
2475                        se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL);
2476                    } else {
2477                        out.writeInt(0);
2478                    }
2479                }
2480            }
2481
2482            int NP = u.mProcessStats.size();
2483            out.writeInt(NP);
2484            if (NP > 0) {
2485                for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent
2486                    : u.mProcessStats.entrySet()) {
2487                    out.writeString(ent.getKey());
2488                    Uid.Proc ps = ent.getValue();
2489                    out.writeLong(ps.mUserTime);
2490                    out.writeLong(ps.mUserTime - ps.mLoadedUserTime);
2491                    out.writeLong(ps.mSystemTime);
2492                    out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime);
2493                    out.writeInt(ps.mStarts);
2494                    out.writeInt(ps.mStarts - ps.mLoadedStarts);
2495                }
2496            }
2497
2498            NP = u.mPackageStats.size();
2499            out.writeInt(NP);
2500            if (NP > 0) {
2501                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
2502                    : u.mPackageStats.entrySet()) {
2503                    out.writeString(ent.getKey());
2504                    Uid.Pkg ps = ent.getValue();
2505                    out.writeInt(ps.mWakeups);
2506                    out.writeInt(ps.mWakeups - ps.mLoadedWakeups);
2507                    final int NS = ps.mServiceStats.size();
2508                    out.writeInt(NS);
2509                    if (NS > 0) {
2510                        for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
2511                                : ps.mServiceStats.entrySet()) {
2512                            out.writeString(sent.getKey());
2513                            BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
2514                            long time = ss.getStartTimeToNowLocked(NOW);
2515                            out.writeLong(time);
2516                            out.writeLong(time - ss.mLoadedStartTime);
2517                            out.writeInt(ss.mStarts);
2518                            out.writeInt(ss.mStarts - ss.mLoadedStarts);
2519                            out.writeInt(ss.mLaunches);
2520                            out.writeInt(ss.mLaunches - ss.mLoadedLaunches);
2521                        }
2522                    }
2523                }
2524            }
2525
2526            out.writeLong(u.getTcpBytesReceived(STATS_TOTAL));
2527            out.writeLong(u.getTcpBytesSent(STATS_TOTAL));
2528        }
2529    }
2530
2531    public void readFromParcel(Parcel in) {
2532        readFromParcelLocked(in);
2533    }
2534
2535    void readFromParcelLocked(Parcel in) {
2536        int magic = in.readInt();
2537        if (magic != MAGIC) {
2538            throw new ParcelFormatException("Bad magic number");
2539        }
2540
2541        mStartCount = in.readInt();
2542        mBatteryUptime = in.readLong();
2543        mBatteryLastUptime = in.readLong();
2544        mBatteryRealtime = in.readLong();
2545        mBatteryLastRealtime = in.readLong();
2546        mScreenOn = false;
2547        mScreenOnTimer = new Timer(-1, null, mUnpluggables, in);
2548        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2549            mScreenBrightnessTimer[i] = new Timer(-100-i, null, mUnpluggables, in);
2550        }
2551        mInputEventCounter = new Counter(mUnpluggables, in);
2552        mPhoneOn = false;
2553        mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in);
2554        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2555            mPhoneSignalStrengthsTimer[i] = new Timer(-200-i, null, mUnpluggables, in);
2556        }
2557        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2558            mPhoneDataConnectionsTimer[i] = new Timer(-300-i, null, mUnpluggables, in);
2559        }
2560        mWifiOn = false;
2561        mWifiOnTimer = new Timer(-2, null, mUnpluggables, in);
2562        mWifiRunning = false;
2563        mWifiRunningTimer = new Timer(-2, null, mUnpluggables, in);
2564        mBluetoothOn = false;
2565        mBluetoothOnTimer = new Timer(-2, null, mUnpluggables, in);
2566        mUptime = in.readLong();
2567        mUptimeStart = in.readLong();
2568        mLastUptime = in.readLong();
2569        mRealtime = in.readLong();
2570        mRealtimeStart = in.readLong();
2571        mLastRealtime = in.readLong();
2572        mOnBattery = in.readInt() != 0;
2573        mOnBatteryInternal = false; // we are no longer really running.
2574        mTrackBatteryPastUptime = in.readLong();
2575        mTrackBatteryUptimeStart = in.readLong();
2576        mTrackBatteryPastRealtime = in.readLong();
2577        mTrackBatteryRealtimeStart = in.readLong();
2578        mUnpluggedBatteryUptime = in.readLong();
2579        mUnpluggedBatteryRealtime = in.readLong();
2580        mUnpluggedStartLevel = in.readInt();
2581        mPluggedStartLevel = in.readInt();
2582        mLastWriteTime = in.readLong();
2583
2584        mPartialTimers.clear();
2585        mFullTimers.clear();
2586        mWindowTimers.clear();
2587
2588        int numUids = in.readInt();
2589        mUidStats.clear();
2590        for (int i = 0; i < numUids; i++) {
2591            int uid = in.readInt();
2592            Uid u = new Uid(uid);
2593            u.readFromParcelLocked(mUnpluggables, in);
2594            mUidStats.append(uid, u);
2595        }
2596    }
2597
2598    public void writeToParcel(Parcel out, int flags) {
2599        writeToParcelLocked(out, flags);
2600    }
2601
2602    @SuppressWarnings("unused")
2603    void writeToParcelLocked(Parcel out, int flags) {
2604        final long uSecUptime = SystemClock.uptimeMillis() * 1000;
2605        final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
2606        final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
2607        final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
2608
2609        out.writeInt(MAGIC);
2610        out.writeInt(mStartCount);
2611        out.writeLong(mBatteryUptime);
2612        out.writeLong(mBatteryLastUptime);
2613        out.writeLong(mBatteryRealtime);
2614        out.writeLong(mBatteryLastRealtime);
2615        mScreenOnTimer.writeToParcel(out, batteryRealtime);
2616        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2617            mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime);
2618        }
2619        mInputEventCounter.writeToParcel(out);
2620        mPhoneOnTimer.writeToParcel(out, batteryRealtime);
2621        for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2622            mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime);
2623        }
2624        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2625            mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
2626        }
2627        mWifiOnTimer.writeToParcel(out, batteryRealtime);
2628        mWifiRunningTimer.writeToParcel(out, batteryRealtime);
2629        mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
2630        out.writeLong(mUptime);
2631        out.writeLong(mUptimeStart);
2632        out.writeLong(mLastUptime);
2633        out.writeLong(mRealtime);
2634        out.writeLong(mRealtimeStart);
2635        out.writeLong(mLastRealtime);
2636        out.writeInt(mOnBattery ? 1 : 0);
2637        out.writeLong(batteryUptime);
2638        out.writeLong(mTrackBatteryUptimeStart);
2639        out.writeLong(batteryRealtime);
2640        out.writeLong(mTrackBatteryRealtimeStart);
2641        out.writeLong(mUnpluggedBatteryUptime);
2642        out.writeLong(mUnpluggedBatteryRealtime);
2643        out.writeInt(mUnpluggedStartLevel);
2644        out.writeInt(mPluggedStartLevel);
2645        out.writeLong(mLastWriteTime);
2646
2647        int size = mUidStats.size();
2648        out.writeInt(size);
2649        for (int i = 0; i < size; i++) {
2650            out.writeInt(mUidStats.keyAt(i));
2651            Uid uid = mUidStats.valueAt(i);
2652
2653            uid.writeToParcelLocked(out, batteryRealtime);
2654        }
2655    }
2656
2657    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
2658        new Parcelable.Creator<BatteryStatsImpl>() {
2659        public BatteryStatsImpl createFromParcel(Parcel in) {
2660            return new BatteryStatsImpl(in);
2661        }
2662
2663        public BatteryStatsImpl[] newArray(int size) {
2664            return new BatteryStatsImpl[size];
2665        }
2666    };
2667
2668    public void dumpLocked(Printer pw) {
2669        if (DEBUG) {
2670            pw.println("*** Screen timer:");
2671            mScreenOnTimer.logState(pw, "  ");
2672            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
2673                pw.println("*** Screen brightness #" + i + ":");
2674                mScreenBrightnessTimer[i].logState(pw, "  ");
2675            }
2676            pw.println("*** Input event counter:");
2677            mInputEventCounter.logState(pw, "  ");
2678            pw.println("*** Phone timer:");
2679            mPhoneOnTimer.logState(pw, "  ");
2680            for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
2681                pw.println("*** Signal strength #" + i + ":");
2682                mPhoneSignalStrengthsTimer[i].logState(pw, "  ");
2683            }
2684            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
2685                pw.println("*** Data connection type #" + i + ":");
2686                mPhoneDataConnectionsTimer[i].logState(pw, "  ");
2687            }
2688            pw.println("*** Wifi timer:");
2689            mWifiOnTimer.logState(pw, "  ");
2690            pw.println("*** WifiRunning timer:");
2691            mWifiRunningTimer.logState(pw, "  ");
2692            pw.println("*** Bluetooth timer:");
2693            mBluetoothOnTimer.logState(pw, "  ");
2694        }
2695        super.dumpLocked(pw);
2696    }
2697}
2698