BatteryStatsImpl.java revision 61659e5daaea80104d4d0fd567e78b5f757b5df4
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 static android.net.NetworkStats.UID_ALL;
20import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
21
22import android.app.ActivityManager;
23import android.bluetooth.BluetoothDevice;
24import android.bluetooth.BluetoothHeadset;
25import android.content.Context;
26import android.net.ConnectivityManager;
27import android.net.NetworkStats;
28import android.net.wifi.WifiManager;
29import android.os.BadParcelableException;
30import android.os.BatteryManager;
31import android.os.BatteryStats;
32import android.os.FileUtils;
33import android.os.Handler;
34import android.os.Looper;
35import android.os.Message;
36import android.os.Parcel;
37import android.os.ParcelFormatException;
38import android.os.Parcelable;
39import android.os.Process;
40import android.os.SystemClock;
41import android.os.SystemProperties;
42import android.os.WorkSource;
43import android.telephony.DataConnectionRealTimeInfo;
44import android.telephony.ServiceState;
45import android.telephony.SignalStrength;
46import android.telephony.TelephonyManager;
47import android.util.ArrayMap;
48import android.util.Log;
49import android.util.LogWriter;
50import android.util.PrintWriterPrinter;
51import android.util.Printer;
52import android.util.Slog;
53import android.util.SparseArray;
54import android.util.SparseIntArray;
55import android.util.TimeUtils;
56import android.view.Display;
57
58import com.android.internal.annotations.GuardedBy;
59import com.android.internal.net.NetworkStatsFactory;
60import com.android.internal.util.ArrayUtils;
61import com.android.internal.util.FastPrintWriter;
62import com.android.internal.util.JournaledFile;
63
64import java.io.File;
65import java.io.FileInputStream;
66import java.io.FileOutputStream;
67import java.io.IOException;
68import java.io.PrintWriter;
69import java.util.ArrayList;
70import java.util.HashMap;
71import java.util.Iterator;
72import java.util.List;
73import java.util.Map;
74import java.util.concurrent.atomic.AtomicInteger;
75import java.util.concurrent.locks.ReentrantLock;
76
77/**
78 * All information we are collecting about things that can happen that impact
79 * battery life.  All times are represented in microseconds except where indicated
80 * otherwise.
81 */
82public final class BatteryStatsImpl extends BatteryStats {
83    private static final String TAG = "BatteryStatsImpl";
84    private static final boolean DEBUG = false;
85    private static final boolean DEBUG_HISTORY = false;
86    private static final boolean USE_OLD_HISTORY = false;   // for debugging.
87
88    // TODO: remove "tcp" from network methods, since we measure total stats.
89
90    // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
91    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
92
93    // Current on-disk Parcel version
94    private static final int VERSION = 109 + (USE_OLD_HISTORY ? 1000 : 0);
95
96    // Maximum number of items we will record in the history.
97    private static final int MAX_HISTORY_ITEMS = 2000;
98
99    // No, really, THIS is the maximum number of items we will record in the history.
100    private static final int MAX_MAX_HISTORY_ITEMS = 3000;
101
102    // The maximum number of names wakelocks we will keep track of
103    // per uid; once the limit is reached, we batch the remaining wakelocks
104    // in to one common name.
105    private static final int MAX_WAKELOCKS_PER_UID = 50;
106
107    private static final String BATCHED_WAKELOCK_NAME = "*overflow*";
108
109    private static int sNumSpeedSteps;
110
111    private final JournaledFile mFile;
112
113    static final int MSG_UPDATE_WAKELOCKS = 1;
114    static final int MSG_REPORT_POWER_CHANGE = 2;
115    static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
116
117    public interface BatteryCallback {
118        public void batteryNeedsCpuUpdate();
119        public void batteryPowerChanged(boolean onBattery);
120    }
121
122    final class MyHandler extends Handler {
123        public MyHandler(Looper looper) {
124            super(looper, null, true);
125        }
126
127        @Override
128        public void handleMessage(Message msg) {
129            BatteryCallback cb = mCallback;
130            switch (msg.what) {
131                case MSG_UPDATE_WAKELOCKS:
132                    if (cb != null) {
133                        cb.batteryNeedsCpuUpdate();
134                    }
135                    break;
136                case MSG_REPORT_POWER_CHANGE:
137                    if (cb != null) {
138                        cb.batteryPowerChanged(msg.arg1 != 0);
139                    }
140                    break;
141            }
142        }
143    }
144
145    private final MyHandler mHandler;
146
147    private BatteryCallback mCallback;
148
149    /**
150     * Mapping isolated uids to the actual owning app uid.
151     */
152    final SparseIntArray mIsolatedUids = new SparseIntArray();
153
154    /**
155     * The statistics we have collected organized by uids.
156     */
157    final SparseArray<BatteryStatsImpl.Uid> mUidStats =
158        new SparseArray<BatteryStatsImpl.Uid>();
159
160    // A set of pools of currently active timers.  When a timer is queried, we will divide the
161    // elapsed time by the number of active timers to arrive at that timer's share of the time.
162    // In order to do this, we must refresh each timer whenever the number of active timers
163    // changes.
164    final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>();
165    final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>();
166    final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
167    final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
168            = new SparseArray<ArrayList<StopwatchTimer>>();
169    final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<StopwatchTimer>();
170    final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
171    final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
172    final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<StopwatchTimer>();
173    final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
174            new SparseArray<ArrayList<StopwatchTimer>>();
175
176    // Last partial timers we use for distributing CPU usage.
177    final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
178
179    // These are the objects that will want to do something when the device
180    // is unplugged from power.
181    final TimeBase mOnBatteryTimeBase = new TimeBase();
182
183    // These are the objects that will want to do something when the device
184    // is unplugged from power *and* the screen is off.
185    final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
186
187    // Set to true when we want to distribute CPU across wakelocks for the next
188    // CPU update, even if we aren't currently running wake locks.
189    boolean mDistributeWakelockCpu;
190
191    boolean mShuttingDown;
192
193    final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
194
195    long mHistoryBaseTime;
196    boolean mHaveBatteryLevel = false;
197    boolean mRecordingHistory = false;
198    int mNumHistoryItems;
199
200    static final int MAX_HISTORY_BUFFER = 128*1024; // 128KB
201    static final int MAX_MAX_HISTORY_BUFFER = 144*1024; // 144KB
202    final Parcel mHistoryBuffer = Parcel.obtain();
203    final HistoryItem mHistoryLastWritten = new HistoryItem();
204    final HistoryItem mHistoryLastLastWritten = new HistoryItem();
205    final HistoryItem mHistoryReadTmp = new HistoryItem();
206    final HistoryItem mHistoryAddTmp = new HistoryItem();
207    final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<HistoryTag, Integer>();
208    String[] mReadHistoryStrings;
209    int[] mReadHistoryUids;
210    int mReadHistoryChars;
211    int mNextHistoryTagIdx = 0;
212    int mNumHistoryTagChars = 0;
213    int mHistoryBufferLastPos = -1;
214    boolean mHistoryOverflow = false;
215    long mLastHistoryElapsedRealtime = 0;
216    long mTrackRunningHistoryElapsedRealtime = 0;
217    long mTrackRunningHistoryUptime = 0;
218
219    final HistoryItem mHistoryCur = new HistoryItem();
220
221    HistoryItem mHistory;
222    HistoryItem mHistoryEnd;
223    HistoryItem mHistoryLastEnd;
224    HistoryItem mHistoryCache;
225
226    private HistoryItem mHistoryIterator;
227    private boolean mReadOverflow;
228    private boolean mIteratingHistory;
229
230    int mStartCount;
231
232    long mStartClockTime;
233
234    long mUptime;
235    long mUptimeStart;
236    long mRealtime;
237    long mRealtimeStart;
238
239    int mWakeLockNesting;
240    boolean mWakeLockImportant;
241    boolean mRecordAllWakeLocks;
242    boolean mNoAutoReset;
243
244    int mScreenState = Display.STATE_UNKNOWN;
245    StopwatchTimer mScreenOnTimer;
246
247    int mScreenBrightnessBin = -1;
248    final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
249
250    boolean mInteractive;
251    StopwatchTimer mInteractiveTimer;
252
253    boolean mLowPowerModeEnabled;
254    StopwatchTimer mLowPowerModeEnabledTimer;
255
256    boolean mPhoneOn;
257    StopwatchTimer mPhoneOnTimer;
258
259    boolean mAudioOn;
260    StopwatchTimer mAudioOnTimer;
261
262    boolean mVideoOn;
263    StopwatchTimer mVideoOnTimer;
264
265    boolean mFlashlightOn;
266    StopwatchTimer mFlashlightOnTimer;
267
268    int mPhoneSignalStrengthBin = -1;
269    int mPhoneSignalStrengthBinRaw = -1;
270    final StopwatchTimer[] mPhoneSignalStrengthsTimer =
271            new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
272
273    StopwatchTimer mPhoneSignalScanningTimer;
274
275    int mPhoneDataConnectionType = -1;
276    final StopwatchTimer[] mPhoneDataConnectionsTimer =
277            new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
278
279    final LongSamplingCounter[] mNetworkByteActivityCounters =
280            new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
281    final LongSamplingCounter[] mNetworkPacketActivityCounters =
282            new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
283
284    boolean mWifiOn;
285    StopwatchTimer mWifiOnTimer;
286
287    boolean mGlobalWifiRunning;
288    StopwatchTimer mGlobalWifiRunningTimer;
289
290    int mWifiState = -1;
291    final StopwatchTimer[] mWifiStateTimer = new StopwatchTimer[NUM_WIFI_STATES];
292
293    int mWifiSupplState = -1;
294    final StopwatchTimer[] mWifiSupplStateTimer = new StopwatchTimer[NUM_WIFI_SUPPL_STATES];
295
296    int mWifiSignalStrengthBin = -1;
297    final StopwatchTimer[] mWifiSignalStrengthsTimer =
298            new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
299
300    boolean mBluetoothOn;
301    StopwatchTimer mBluetoothOnTimer;
302
303    int mBluetoothState = -1;
304    final StopwatchTimer[] mBluetoothStateTimer = new StopwatchTimer[NUM_BLUETOOTH_STATES];
305
306    int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
307    long mMobileRadioActiveStartTime;
308    StopwatchTimer mMobileRadioActiveTimer;
309    StopwatchTimer mMobileRadioActivePerAppTimer;
310    LongSamplingCounter mMobileRadioActiveAdjustedTime;
311    LongSamplingCounter mMobileRadioActiveUnknownTime;
312    LongSamplingCounter mMobileRadioActiveUnknownCount;
313
314    /** Bluetooth headset object */
315    BluetoothHeadset mBtHeadset;
316
317    /**
318     * These provide time bases that discount the time the device is plugged
319     * in to power.
320     */
321    boolean mOnBattery;
322    boolean mOnBatteryInternal;
323
324    /*
325     * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
326     */
327    int mDischargeStartLevel;
328    int mDischargeUnplugLevel;
329    int mDischargePlugLevel;
330    int mDischargeCurrentLevel;
331    int mCurrentBatteryLevel;
332    int mLowDischargeAmountSinceCharge;
333    int mHighDischargeAmountSinceCharge;
334    int mDischargeScreenOnUnplugLevel;
335    int mDischargeScreenOffUnplugLevel;
336    int mDischargeAmountScreenOn;
337    int mDischargeAmountScreenOnSinceCharge;
338    int mDischargeAmountScreenOff;
339    int mDischargeAmountScreenOffSinceCharge;
340
341    static final int MAX_LEVEL_STEPS = 100;
342
343    int mLastDischargeStepLevel;
344    long mLastDischargeStepTime;
345    int mMinDischargeStepLevel;
346    int mNumDischargeStepDurations;
347    final long[] mDischargeStepDurations = new long[MAX_LEVEL_STEPS];
348
349    int mLastChargeStepLevel;
350    long mLastChargeStepTime;
351    int mMaxChargeStepLevel;
352    int mNumChargeStepDurations;
353    final long[] mChargeStepDurations = new long[MAX_LEVEL_STEPS];
354
355    long mLastWriteTime = 0; // Milliseconds
356
357    private int mBluetoothPingCount;
358    private int mBluetoothPingStart = -1;
359
360    private int mPhoneServiceState = -1;
361    private int mPhoneServiceStateRaw = -1;
362    private int mPhoneSimStateRaw = -1;
363
364    /*
365     * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
366     */
367    private final HashMap<String, SamplingTimer> mKernelWakelockStats =
368            new HashMap<String, SamplingTimer>();
369
370    public Map<String, ? extends Timer> getKernelWakelockStats() {
371        return mKernelWakelockStats;
372    }
373
374    private static int sKernelWakelockUpdateVersion = 0;
375
376    String mLastWakeupReason = null;
377    long mLastWakeupUptimeMs = 0;
378    private final HashMap<String, LongSamplingCounter> mWakeupReasonStats =
379            new HashMap<String, LongSamplingCounter>();
380
381    public Map<String, ? extends LongCounter> getWakeupReasonStats() {
382        return mWakeupReasonStats;
383    }
384
385    private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
386        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING|                // 0: name
387                              Process.PROC_QUOTES,
388        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
389        Process.PROC_TAB_TERM,
390        Process.PROC_TAB_TERM,
391        Process.PROC_TAB_TERM,
392        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
393    };
394
395    private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
396        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
397        Process.PROC_TAB_TERM|Process.PROC_COMBINE|
398                              Process.PROC_OUT_LONG,                  // 1: count
399        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
400        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
401        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
402        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
403        Process.PROC_TAB_TERM|Process.PROC_COMBINE
404                             |Process.PROC_OUT_LONG,                  // 6: totalTime
405    };
406
407    private final String[] mProcWakelocksName = new String[3];
408    private final long[] mProcWakelocksData = new long[3];
409
410    /*
411     * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
412     * to mKernelWakelockStats.
413     */
414    private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
415            new HashMap<String, KernelWakelockStats>();
416
417    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
418    private NetworkStats mCurMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
419    private NetworkStats mLastMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
420    private NetworkStats mCurWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
421    private NetworkStats mLastWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
422    private NetworkStats mTmpNetworkStats;
423    private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
424
425    @GuardedBy("this")
426    private String[] mMobileIfaces = new String[0];
427    @GuardedBy("this")
428    private String[] mWifiIfaces = new String[0];
429
430    // For debugging
431    public BatteryStatsImpl() {
432        mFile = null;
433        mHandler = null;
434    }
435
436    public static interface TimeBaseObs {
437        void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
438        void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
439    }
440
441    static class TimeBase {
442        private final ArrayList<TimeBaseObs> mObservers = new ArrayList<TimeBaseObs>();
443
444        private long mUptime;
445        private long mRealtime;
446
447        private boolean mRunning;
448
449        private long mPastUptime;
450        private long mUptimeStart;
451        private long mPastRealtime;
452        private long mRealtimeStart;
453        private long mUnpluggedUptime;
454        private long mUnpluggedRealtime;
455
456        public void dump(PrintWriter pw, String prefix) {
457            StringBuilder sb = new StringBuilder(128);
458            pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
459            sb.setLength(0);
460            sb.append(prefix);
461                    sb.append("mUptime=");
462                    formatTimeMs(sb, mUptime / 1000);
463            pw.println(sb.toString());
464            sb.setLength(0);
465            sb.append(prefix);
466                    sb.append("mRealtime=");
467                    formatTimeMs(sb, mRealtime / 1000);
468            pw.println(sb.toString());
469            sb.setLength(0);
470            sb.append(prefix);
471                    sb.append("mPastUptime=");
472                    formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
473                    formatTimeMs(sb, mUptimeStart / 1000);
474                    sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
475            pw.println(sb.toString());
476            sb.setLength(0);
477            sb.append(prefix);
478                    sb.append("mPastRealtime=");
479                    formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
480                    formatTimeMs(sb, mRealtimeStart / 1000);
481                    sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
482            pw.println(sb.toString());
483        }
484
485        public void add(TimeBaseObs observer) {
486            mObservers.add(observer);
487        }
488
489        public void remove(TimeBaseObs observer) {
490            if (!mObservers.remove(observer)) {
491                Slog.wtf(TAG, "Removed unknown observer: " + observer);
492            }
493        }
494
495        public void init(long uptime, long realtime) {
496            mRealtime = 0;
497            mUptime = 0;
498            mPastUptime = 0;
499            mPastRealtime = 0;
500            mUptimeStart = uptime;
501            mRealtimeStart = realtime;
502            mUnpluggedUptime = getUptime(mUptimeStart);
503            mUnpluggedRealtime = getRealtime(mRealtimeStart);
504        }
505
506        public void reset(long uptime, long realtime) {
507            if (!mRunning) {
508                mPastUptime = 0;
509                mPastRealtime = 0;
510            } else {
511                mUptimeStart = uptime;
512                mRealtimeStart = realtime;
513                mUnpluggedUptime = getUptime(uptime);
514                mUnpluggedRealtime = getRealtime(realtime);
515            }
516        }
517
518        public long computeUptime(long curTime, int which) {
519            switch (which) {
520                case STATS_SINCE_CHARGED:
521                    return mUptime + getUptime(curTime);
522                case STATS_CURRENT:
523                    return getUptime(curTime);
524                case STATS_SINCE_UNPLUGGED:
525                    return getUptime(curTime) - mUnpluggedUptime;
526            }
527            return 0;
528        }
529
530        public long computeRealtime(long curTime, int which) {
531            switch (which) {
532                case STATS_SINCE_CHARGED:
533                    return mRealtime + getRealtime(curTime);
534                case STATS_CURRENT:
535                    return getRealtime(curTime);
536                case STATS_SINCE_UNPLUGGED:
537                    return getRealtime(curTime) - mUnpluggedRealtime;
538            }
539            return 0;
540        }
541
542        public long getUptime(long curTime) {
543            long time = mPastUptime;
544            if (mRunning) {
545                time += curTime - mUptimeStart;
546            }
547            return time;
548        }
549
550        public long getRealtime(long curTime) {
551            long time = mPastRealtime;
552            if (mRunning) {
553                time += curTime - mRealtimeStart;
554            }
555            return time;
556        }
557
558        public long getUptimeStart() {
559            return mUptimeStart;
560        }
561
562        public long getRealtimeStart() {
563            return mRealtimeStart;
564        }
565
566        public boolean isRunning() {
567            return mRunning;
568        }
569
570        public boolean setRunning(boolean running, long uptime, long realtime) {
571            if (mRunning != running) {
572                mRunning = running;
573                if (running) {
574                    mUptimeStart = uptime;
575                    mRealtimeStart = realtime;
576                    long batteryUptime = mUnpluggedUptime = getUptime(uptime);
577                    long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
578
579                    for (int i = mObservers.size() - 1; i >= 0; i--) {
580                        mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
581                    }
582                } else {
583                    mPastUptime += uptime - mUptimeStart;
584                    mPastRealtime += realtime - mRealtimeStart;
585
586                    long batteryUptime = getUptime(uptime);
587                    long batteryRealtime = getRealtime(realtime);
588
589                    for (int i = mObservers.size() - 1; i >= 0; i--) {
590                        mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
591                    }
592                }
593                return true;
594            }
595            return false;
596        }
597
598        public void readSummaryFromParcel(Parcel in) {
599            mUptime = in.readLong();
600            mRealtime = in.readLong();
601        }
602
603        public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
604            out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
605            out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
606        }
607
608        public void readFromParcel(Parcel in) {
609            mRunning = false;
610            mUptime = in.readLong();
611            mPastUptime = in.readLong();
612            mUptimeStart = in.readLong();
613            mRealtime = in.readLong();
614            mPastRealtime = in.readLong();
615            mRealtimeStart = in.readLong();
616            mUnpluggedUptime = in.readLong();
617            mUnpluggedRealtime = in.readLong();
618        }
619
620        public void writeToParcel(Parcel out, long uptime, long realtime) {
621            final long runningUptime = getUptime(uptime);
622            final long runningRealtime = getRealtime(realtime);
623            out.writeLong(mUptime);
624            out.writeLong(runningUptime);
625            out.writeLong(mUptimeStart);
626            out.writeLong(mRealtime);
627            out.writeLong(runningRealtime);
628            out.writeLong(mRealtimeStart);
629            out.writeLong(mUnpluggedUptime);
630            out.writeLong(mUnpluggedRealtime);
631        }
632    }
633
634    /**
635     * State for keeping track of counting information.
636     */
637    public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
638        final AtomicInteger mCount = new AtomicInteger();
639        final TimeBase mTimeBase;
640        int mLoadedCount;
641        int mLastCount;
642        int mUnpluggedCount;
643        int mPluggedCount;
644
645        Counter(TimeBase timeBase, Parcel in) {
646            mTimeBase = timeBase;
647            mPluggedCount = in.readInt();
648            mCount.set(mPluggedCount);
649            mLoadedCount = in.readInt();
650            mLastCount = 0;
651            mUnpluggedCount = in.readInt();
652            timeBase.add(this);
653        }
654
655        Counter(TimeBase timeBase) {
656            mTimeBase = timeBase;
657            timeBase.add(this);
658        }
659
660        public void writeToParcel(Parcel out) {
661            out.writeInt(mCount.get());
662            out.writeInt(mLoadedCount);
663            out.writeInt(mUnpluggedCount);
664        }
665
666        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
667            mUnpluggedCount = mPluggedCount;
668            mCount.set(mPluggedCount);
669        }
670
671        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
672            mPluggedCount = mCount.get();
673        }
674
675        /**
676         * Writes a possibly null Counter to a Parcel.
677         *
678         * @param out the Parcel to be written to.
679         * @param counter a Counter, or null.
680         */
681        public static void writeCounterToParcel(Parcel out, Counter counter) {
682            if (counter == null) {
683                out.writeInt(0); // indicates null
684                return;
685            }
686            out.writeInt(1); // indicates non-null
687
688            counter.writeToParcel(out);
689        }
690
691        @Override
692        public int getCountLocked(int which) {
693            int val = mCount.get();
694            if (which == STATS_SINCE_UNPLUGGED) {
695                val -= mUnpluggedCount;
696            } else if (which != STATS_SINCE_CHARGED) {
697                val -= mLoadedCount;
698            }
699
700            return val;
701        }
702
703        public void logState(Printer pw, String prefix) {
704            pw.println(prefix + "mCount=" + mCount.get()
705                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
706                    + " mUnpluggedCount=" + mUnpluggedCount
707                    + " mPluggedCount=" + mPluggedCount);
708        }
709
710        void stepAtomic() {
711            mCount.incrementAndGet();
712        }
713
714        /**
715         * Clear state of this counter.
716         */
717        void reset(boolean detachIfReset) {
718            mCount.set(0);
719            mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
720            if (detachIfReset) {
721                detach();
722            }
723        }
724
725        void detach() {
726            mTimeBase.remove(this);
727        }
728
729        void writeSummaryFromParcelLocked(Parcel out) {
730            int count = mCount.get();
731            out.writeInt(count);
732        }
733
734        void readSummaryFromParcelLocked(Parcel in) {
735            mLoadedCount = in.readInt();
736            mCount.set(mLoadedCount);
737            mLastCount = 0;
738            mUnpluggedCount = mPluggedCount = mLoadedCount;
739        }
740    }
741
742    public static class SamplingCounter extends Counter {
743        SamplingCounter(TimeBase timeBase, Parcel in) {
744            super(timeBase, in);
745        }
746
747        SamplingCounter(TimeBase timeBase) {
748            super(timeBase);
749        }
750
751        public void addCountAtomic(long count) {
752            mCount.addAndGet((int)count);
753        }
754    }
755
756    public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
757        final TimeBase mTimeBase;
758        long mCount;
759        long mLoadedCount;
760        long mLastCount;
761        long mUnpluggedCount;
762        long mPluggedCount;
763
764        LongSamplingCounter(TimeBase timeBase, Parcel in) {
765            mTimeBase = timeBase;
766            mPluggedCount = in.readLong();
767            mCount = mPluggedCount;
768            mLoadedCount = in.readLong();
769            mLastCount = 0;
770            mUnpluggedCount = in.readLong();
771            timeBase.add(this);
772        }
773
774        LongSamplingCounter(TimeBase timeBase) {
775            mTimeBase = timeBase;
776            timeBase.add(this);
777        }
778
779        public void writeToParcel(Parcel out) {
780            out.writeLong(mCount);
781            out.writeLong(mLoadedCount);
782            out.writeLong(mUnpluggedCount);
783        }
784
785        @Override
786        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
787            mUnpluggedCount = mPluggedCount;
788            mCount = mPluggedCount;
789        }
790
791        @Override
792        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
793            mPluggedCount = mCount;
794        }
795
796        public long getCountLocked(int which) {
797            long val = mCount;
798            if (which == STATS_SINCE_UNPLUGGED) {
799                val -= mUnpluggedCount;
800            } else if (which != STATS_SINCE_CHARGED) {
801                val -= mLoadedCount;
802            }
803
804            return val;
805        }
806
807        @Override
808        public void logState(Printer pw, String prefix) {
809            pw.println(prefix + "mCount=" + mCount
810                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
811                    + " mUnpluggedCount=" + mUnpluggedCount
812                    + " mPluggedCount=" + mPluggedCount);
813        }
814
815        void addCountLocked(long count) {
816            mCount += count;
817        }
818
819        /**
820         * Clear state of this counter.
821         */
822        void reset(boolean detachIfReset) {
823            mCount = 0;
824            mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
825            if (detachIfReset) {
826                detach();
827            }
828        }
829
830        void detach() {
831            mTimeBase.remove(this);
832        }
833
834        void writeSummaryFromParcelLocked(Parcel out) {
835            out.writeLong(mCount);
836        }
837
838        void readSummaryFromParcelLocked(Parcel in) {
839            mLoadedCount = in.readLong();
840            mCount = mLoadedCount;
841            mLastCount = 0;
842            mUnpluggedCount = mPluggedCount = mLoadedCount;
843        }
844    }
845
846    /**
847     * State for keeping track of timing information.
848     */
849    public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
850        final int mType;
851        final TimeBase mTimeBase;
852
853        int mCount;
854        int mLoadedCount;
855        int mLastCount;
856        int mUnpluggedCount;
857
858        // Times are in microseconds for better accuracy when dividing by the
859        // lock count, and are in "battery realtime" units.
860
861        /**
862         * The total time we have accumulated since the start of the original
863         * boot, to the last time something interesting happened in the
864         * current run.
865         */
866        long mTotalTime;
867
868        /**
869         * The total time we loaded for the previous runs.  Subtract this from
870         * mTotalTime to find the time for the current run of the system.
871         */
872        long mLoadedTime;
873
874        /**
875         * The run time of the last run of the system, as loaded from the
876         * saved data.
877         */
878        long mLastTime;
879
880        /**
881         * The value of mTotalTime when unplug() was last called.  Subtract
882         * this from mTotalTime to find the time since the last unplug from
883         * power.
884         */
885        long mUnpluggedTime;
886
887        /**
888         * Constructs from a parcel.
889         * @param type
890         * @param timeBase
891         * @param in
892         */
893        Timer(int type, TimeBase timeBase, Parcel in) {
894            mType = type;
895            mTimeBase = timeBase;
896
897            mCount = in.readInt();
898            mLoadedCount = in.readInt();
899            mLastCount = 0;
900            mUnpluggedCount = in.readInt();
901            mTotalTime = in.readLong();
902            mLoadedTime = in.readLong();
903            mLastTime = 0;
904            mUnpluggedTime = in.readLong();
905            timeBase.add(this);
906            if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
907        }
908
909        Timer(int type, TimeBase timeBase) {
910            mType = type;
911            mTimeBase = timeBase;
912            timeBase.add(this);
913        }
914
915        protected abstract long computeRunTimeLocked(long curBatteryRealtime);
916
917        protected abstract int computeCurrentCountLocked();
918
919        /**
920         * Clear state of this timer.  Returns true if the timer is inactive
921         * so can be completely dropped.
922         */
923        boolean reset(boolean detachIfReset) {
924            mTotalTime = mLoadedTime = mLastTime = 0;
925            mCount = mLoadedCount = mLastCount = 0;
926            if (detachIfReset) {
927                detach();
928            }
929            return true;
930        }
931
932        void detach() {
933            mTimeBase.remove(this);
934        }
935
936        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
937            if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
938                    + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
939            out.writeInt(mCount);
940            out.writeInt(mLoadedCount);
941            out.writeInt(mUnpluggedCount);
942            out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
943            out.writeLong(mLoadedTime);
944            out.writeLong(mUnpluggedTime);
945        }
946
947        public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
948            if (DEBUG && mType < 0) {
949                Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
950                        + " old mUnpluggedTime=" + mUnpluggedTime
951                        + " old mUnpluggedCount=" + mUnpluggedCount);
952            }
953            mUnpluggedTime = computeRunTimeLocked(baseRealtime);
954            mUnpluggedCount = mCount;
955            if (DEBUG && mType < 0) {
956                Log.v(TAG, "unplug #" + mType
957                        + ": new mUnpluggedTime=" + mUnpluggedTime
958                        + " new mUnpluggedCount=" + mUnpluggedCount);
959            }
960        }
961
962        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
963            if (DEBUG && mType < 0) {
964                Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
965                        + " old mTotalTime=" + mTotalTime);
966            }
967            mTotalTime = computeRunTimeLocked(baseRealtime);
968            mCount = computeCurrentCountLocked();
969            if (DEBUG && mType < 0) {
970                Log.v(TAG, "plug #" + mType
971                        + ": new mTotalTime=" + mTotalTime);
972            }
973        }
974
975        /**
976         * Writes a possibly null Timer to a Parcel.
977         *
978         * @param out the Parcel to be written to.
979         * @param timer a Timer, or null.
980         */
981        public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
982            if (timer == null) {
983                out.writeInt(0); // indicates null
984                return;
985            }
986            out.writeInt(1); // indicates non-null
987
988            timer.writeToParcel(out, elapsedRealtimeUs);
989        }
990
991        @Override
992        public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
993            long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
994            if (which == STATS_SINCE_UNPLUGGED) {
995                val -= mUnpluggedTime;
996            } else if (which != STATS_SINCE_CHARGED) {
997                val -= mLoadedTime;
998            }
999
1000            return val;
1001        }
1002
1003        @Override
1004        public int getCountLocked(int which) {
1005            int val = computeCurrentCountLocked();
1006            if (which == STATS_SINCE_UNPLUGGED) {
1007                val -= mUnpluggedCount;
1008            } else if (which != STATS_SINCE_CHARGED) {
1009                val -= mLoadedCount;
1010            }
1011
1012            return val;
1013        }
1014
1015        public void logState(Printer pw, String prefix) {
1016            pw.println(prefix + "mCount=" + mCount
1017                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
1018                    + " mUnpluggedCount=" + mUnpluggedCount);
1019            pw.println(prefix + "mTotalTime=" + mTotalTime
1020                    + " mLoadedTime=" + mLoadedTime);
1021            pw.println(prefix + "mLastTime=" + mLastTime
1022                    + " mUnpluggedTime=" + mUnpluggedTime);
1023        }
1024
1025
1026        void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
1027            long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
1028            out.writeLong(runTime);
1029            out.writeInt(mCount);
1030        }
1031
1032        void readSummaryFromParcelLocked(Parcel in) {
1033            // Multiply by 1000 for backwards compatibility
1034            mTotalTime = mLoadedTime = in.readLong();
1035            mLastTime = 0;
1036            mUnpluggedTime = mTotalTime;
1037            mCount = mLoadedCount = in.readInt();
1038            mLastCount = 0;
1039            mUnpluggedCount = mCount;
1040        }
1041    }
1042
1043    public static final class SamplingTimer extends Timer {
1044
1045        /**
1046         * The most recent reported count from /proc/wakelocks.
1047         */
1048        int mCurrentReportedCount;
1049
1050        /**
1051         * The reported count from /proc/wakelocks when unplug() was last
1052         * called.
1053         */
1054        int mUnpluggedReportedCount;
1055
1056        /**
1057         * The most recent reported total_time from /proc/wakelocks.
1058         */
1059        long mCurrentReportedTotalTime;
1060
1061
1062        /**
1063         * The reported total_time from /proc/wakelocks when unplug() was last
1064         * called.
1065         */
1066        long mUnpluggedReportedTotalTime;
1067
1068        /**
1069         * Whether we are currently in a discharge cycle.
1070         */
1071        boolean mTimeBaseRunning;
1072
1073        /**
1074         * Whether we are currently recording reported values.
1075         */
1076        boolean mTrackingReportedValues;
1077
1078        /*
1079         * A sequence counter, incremented once for each update of the stats.
1080         */
1081        int mUpdateVersion;
1082
1083        SamplingTimer(TimeBase timeBase, Parcel in) {
1084            super(0, timeBase, in);
1085            mCurrentReportedCount = in.readInt();
1086            mUnpluggedReportedCount = in.readInt();
1087            mCurrentReportedTotalTime = in.readLong();
1088            mUnpluggedReportedTotalTime = in.readLong();
1089            mTrackingReportedValues = in.readInt() == 1;
1090            mTimeBaseRunning = timeBase.isRunning();
1091        }
1092
1093        SamplingTimer(TimeBase timeBase, boolean trackReportedValues) {
1094            super(0, timeBase);
1095            mTrackingReportedValues = trackReportedValues;
1096            mTimeBaseRunning = timeBase.isRunning();
1097        }
1098
1099        public void setStale() {
1100            mTrackingReportedValues = false;
1101            mUnpluggedReportedTotalTime = 0;
1102            mUnpluggedReportedCount = 0;
1103        }
1104
1105        public void setUpdateVersion(int version) {
1106            mUpdateVersion = version;
1107        }
1108
1109        public int getUpdateVersion() {
1110            return mUpdateVersion;
1111        }
1112
1113        public void updateCurrentReportedCount(int count) {
1114            if (mTimeBaseRunning && mUnpluggedReportedCount == 0) {
1115                // Updating the reported value for the first time.
1116                mUnpluggedReportedCount = count;
1117                // If we are receiving an update update mTrackingReportedValues;
1118                mTrackingReportedValues = true;
1119            }
1120            mCurrentReportedCount = count;
1121        }
1122
1123        public void updateCurrentReportedTotalTime(long totalTime) {
1124            if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) {
1125                // Updating the reported value for the first time.
1126                mUnpluggedReportedTotalTime = totalTime;
1127                // If we are receiving an update update mTrackingReportedValues;
1128                mTrackingReportedValues = true;
1129            }
1130            mCurrentReportedTotalTime = totalTime;
1131        }
1132
1133        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1134            super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1135            if (mTrackingReportedValues) {
1136                mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
1137                mUnpluggedReportedCount = mCurrentReportedCount;
1138            }
1139            mTimeBaseRunning = true;
1140        }
1141
1142        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1143            super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1144            mTimeBaseRunning = false;
1145        }
1146
1147        public void logState(Printer pw, String prefix) {
1148            super.logState(pw, prefix);
1149            pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
1150                    + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
1151                    + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
1152                    + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
1153        }
1154
1155        protected long computeRunTimeLocked(long curBatteryRealtime) {
1156            return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
1157                    ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
1158        }
1159
1160        protected int computeCurrentCountLocked() {
1161            return mCount + (mTimeBaseRunning && mTrackingReportedValues
1162                    ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
1163        }
1164
1165        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1166            super.writeToParcel(out, elapsedRealtimeUs);
1167            out.writeInt(mCurrentReportedCount);
1168            out.writeInt(mUnpluggedReportedCount);
1169            out.writeLong(mCurrentReportedTotalTime);
1170            out.writeLong(mUnpluggedReportedTotalTime);
1171            out.writeInt(mTrackingReportedValues ? 1 : 0);
1172        }
1173
1174        boolean reset(boolean detachIfReset) {
1175            super.reset(detachIfReset);
1176            setStale();
1177            return true;
1178        }
1179
1180        void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
1181            super.writeSummaryFromParcelLocked(out, batteryRealtime);
1182            out.writeLong(mCurrentReportedTotalTime);
1183            out.writeInt(mCurrentReportedCount);
1184            out.writeInt(mTrackingReportedValues ? 1 : 0);
1185        }
1186
1187        void readSummaryFromParcelLocked(Parcel in) {
1188            super.readSummaryFromParcelLocked(in);
1189            mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
1190            mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
1191            mTrackingReportedValues = in.readInt() == 1;
1192        }
1193    }
1194
1195    /**
1196     * A timer that increments in batches.  It does not run for durations, but just jumps
1197     * for a pre-determined amount.
1198     */
1199    public static final class BatchTimer extends Timer {
1200        final Uid mUid;
1201
1202        /**
1203         * The last time at which we updated the timer.  This is in elapsed realtime microseconds.
1204         */
1205        long mLastAddedTime;
1206
1207        /**
1208         * The last duration that we added to the timer.  This is in microseconds.
1209         */
1210        long mLastAddedDuration;
1211
1212        /**
1213         * Whether we are currently in a discharge cycle.
1214         */
1215        boolean mInDischarge;
1216
1217        BatchTimer(Uid uid, int type, TimeBase timeBase, Parcel in) {
1218            super(type, timeBase, in);
1219            mUid = uid;
1220            mLastAddedTime = in.readLong();
1221            mLastAddedDuration = in.readLong();
1222            mInDischarge = timeBase.isRunning();
1223        }
1224
1225        BatchTimer(Uid uid, int type, TimeBase timeBase) {
1226            super(type, timeBase);
1227            mUid = uid;
1228            mInDischarge = timeBase.isRunning();
1229        }
1230
1231        @Override
1232        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1233            super.writeToParcel(out, elapsedRealtimeUs);
1234            out.writeLong(mLastAddedTime);
1235            out.writeLong(mLastAddedDuration);
1236        }
1237
1238        @Override
1239        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1240            recomputeLastDuration(SystemClock.elapsedRealtime() * 1000, false);
1241            mInDischarge = false;
1242            super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1243        }
1244
1245        @Override
1246        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
1247            recomputeLastDuration(elapsedRealtime, false);
1248            mInDischarge = true;
1249            // If we are still within the last added duration, then re-added whatever remains.
1250            if (mLastAddedTime == elapsedRealtime) {
1251                mTotalTime += mLastAddedDuration;
1252            }
1253            super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
1254        }
1255
1256        @Override
1257        public void logState(Printer pw, String prefix) {
1258            super.logState(pw, prefix);
1259            pw.println(prefix + "mLastAddedTime=" + mLastAddedTime
1260                    + " mLastAddedDuration=" + mLastAddedDuration);
1261        }
1262
1263        private long computeOverage(long curTime) {
1264            if (mLastAddedTime > 0) {
1265                return mLastTime + mLastAddedDuration - curTime;
1266            }
1267            return 0;
1268        }
1269
1270        private void recomputeLastDuration(long curTime, boolean abort) {
1271            final long overage = computeOverage(curTime);
1272            if (overage > 0) {
1273                // Aborting before the duration ran out -- roll back the remaining
1274                // duration.  Only do this if currently discharging; otherwise we didn't
1275                // actually add the time.
1276                if (mInDischarge) {
1277                    mTotalTime -= overage;
1278                }
1279                if (abort) {
1280                    mLastAddedTime = 0;
1281                } else {
1282                    mLastAddedTime = curTime;
1283                    mLastAddedDuration -= overage;
1284                }
1285            }
1286        }
1287
1288        public void addDuration(BatteryStatsImpl stats, long durationMillis) {
1289            final long now = SystemClock.elapsedRealtime() * 1000;
1290            recomputeLastDuration(now, true);
1291            mLastAddedTime = now;
1292            mLastAddedDuration = durationMillis * 1000;
1293            if (mInDischarge) {
1294                mTotalTime += mLastAddedDuration;
1295                mCount++;
1296            }
1297        }
1298
1299        public void abortLastDuration(BatteryStatsImpl stats) {
1300            final long now = SystemClock.elapsedRealtime() * 1000;
1301            recomputeLastDuration(now, true);
1302        }
1303
1304        @Override
1305        protected int computeCurrentCountLocked() {
1306            return mCount;
1307        }
1308
1309        @Override
1310        protected long computeRunTimeLocked(long curBatteryRealtime) {
1311            final long overage = computeOverage(SystemClock.elapsedRealtime() * 1000);
1312            if (overage > 0) {
1313                return mTotalTime = overage;
1314            }
1315            return mTotalTime;
1316        }
1317
1318        @Override
1319        boolean reset(boolean detachIfReset) {
1320            final long now = SystemClock.elapsedRealtime() * 1000;
1321            recomputeLastDuration(now, true);
1322            boolean stillActive = mLastAddedTime == now;
1323            super.reset(!stillActive && detachIfReset);
1324            return !stillActive;
1325        }
1326    }
1327
1328    /**
1329     * State for keeping track of timing information.
1330     */
1331    public static final class StopwatchTimer extends Timer {
1332        final Uid mUid;
1333        final ArrayList<StopwatchTimer> mTimerPool;
1334
1335        int mNesting;
1336
1337        /**
1338         * The last time at which we updated the timer.  If mNesting is > 0,
1339         * subtract this from the current battery time to find the amount of
1340         * time we have been running since we last computed an update.
1341         */
1342        long mUpdateTime;
1343
1344        /**
1345         * The total time at which the timer was acquired, to determine if it
1346         * was actually held for an interesting duration.
1347         */
1348        long mAcquireTime;
1349
1350        long mTimeout;
1351
1352        /**
1353         * For partial wake locks, keep track of whether we are in the list
1354         * to consume CPU cycles.
1355         */
1356        boolean mInList;
1357
1358        StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
1359                TimeBase timeBase, Parcel in) {
1360            super(type, timeBase, in);
1361            mUid = uid;
1362            mTimerPool = timerPool;
1363            mUpdateTime = in.readLong();
1364        }
1365
1366        StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
1367                TimeBase timeBase) {
1368            super(type, timeBase);
1369            mUid = uid;
1370            mTimerPool = timerPool;
1371        }
1372
1373        void setTimeout(long timeout) {
1374            mTimeout = timeout;
1375        }
1376
1377        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
1378            super.writeToParcel(out, elapsedRealtimeUs);
1379            out.writeLong(mUpdateTime);
1380        }
1381
1382        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
1383            if (mNesting > 0) {
1384                if (DEBUG && mType < 0) {
1385                    Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
1386                }
1387                super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
1388                mUpdateTime = baseRealtime;
1389                if (DEBUG && mType < 0) {
1390                    Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
1391                }
1392            }
1393        }
1394
1395        public void logState(Printer pw, String prefix) {
1396            super.logState(pw, prefix);
1397            pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime
1398                    + " mAcquireTime=" + mAcquireTime);
1399        }
1400
1401        void startRunningLocked(long elapsedRealtimeMs) {
1402            if (mNesting++ == 0) {
1403                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
1404                mUpdateTime = batteryRealtime;
1405                if (mTimerPool != null) {
1406                    // Accumulate time to all currently active timers before adding
1407                    // this new one to the pool.
1408                    refreshTimersLocked(batteryRealtime, mTimerPool, null);
1409                    // Add this timer to the active pool
1410                    mTimerPool.add(this);
1411                }
1412                // Increment the count
1413                mCount++;
1414                mAcquireTime = mTotalTime;
1415                if (DEBUG && mType < 0) {
1416                    Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
1417                            + " mTotalTime=" + mTotalTime + " mCount=" + mCount
1418                            + " mAcquireTime=" + mAcquireTime);
1419                }
1420            }
1421        }
1422
1423        boolean isRunningLocked() {
1424            return mNesting > 0;
1425        }
1426
1427        long checkpointRunningLocked(long elapsedRealtimeMs) {
1428            if (mNesting > 0) {
1429                // We are running...
1430                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
1431                if (mTimerPool != null) {
1432                    return refreshTimersLocked(batteryRealtime, mTimerPool, this);
1433                }
1434                final long heldTime = batteryRealtime - mUpdateTime;
1435                mUpdateTime = batteryRealtime;
1436                mTotalTime += heldTime;
1437                return heldTime;
1438            }
1439            return 0;
1440        }
1441
1442        void stopRunningLocked(long elapsedRealtimeMs) {
1443            // Ignore attempt to stop a timer that isn't running
1444            if (mNesting == 0) {
1445                return;
1446            }
1447            if (--mNesting == 0) {
1448                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
1449                if (mTimerPool != null) {
1450                    // Accumulate time to all active counters, scaled by the total
1451                    // active in the pool, before taking this one out of the pool.
1452                    refreshTimersLocked(batteryRealtime, mTimerPool, null);
1453                    // Remove this timer from the active pool
1454                    mTimerPool.remove(this);
1455                } else {
1456                    mNesting = 1;
1457                    mTotalTime = computeRunTimeLocked(batteryRealtime);
1458                    mNesting = 0;
1459                }
1460
1461                if (DEBUG && mType < 0) {
1462                    Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
1463                            + " mTotalTime=" + mTotalTime + " mCount=" + mCount
1464                            + " mAcquireTime=" + mAcquireTime);
1465                }
1466
1467                if (mTotalTime == mAcquireTime) {
1468                    // If there was no change in the time, then discard this
1469                    // count.  A somewhat cheezy strategy, but hey.
1470                    mCount--;
1471                }
1472            }
1473        }
1474
1475        // Update the total time for all other running Timers with the same type as this Timer
1476        // due to a change in timer count
1477        private static long refreshTimersLocked(long batteryRealtime,
1478                final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
1479            long selfTime = 0;
1480            final int N = pool.size();
1481            for (int i=N-1; i>= 0; i--) {
1482                final StopwatchTimer t = pool.get(i);
1483                long heldTime = batteryRealtime - t.mUpdateTime;
1484                if (heldTime > 0) {
1485                    final long myTime = heldTime / N;
1486                    if (t == self) {
1487                        selfTime = myTime;
1488                    }
1489                    t.mTotalTime += myTime;
1490                }
1491                t.mUpdateTime = batteryRealtime;
1492            }
1493            return selfTime;
1494        }
1495
1496        @Override
1497        protected long computeRunTimeLocked(long curBatteryRealtime) {
1498            if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) {
1499                curBatteryRealtime = mUpdateTime + mTimeout;
1500            }
1501            return mTotalTime + (mNesting > 0
1502                    ? (curBatteryRealtime - mUpdateTime)
1503                            / (mTimerPool != null ? mTimerPool.size() : 1)
1504                    : 0);
1505        }
1506
1507        @Override
1508        protected int computeCurrentCountLocked() {
1509            return mCount;
1510        }
1511
1512        boolean reset(boolean detachIfReset) {
1513            boolean canDetach = mNesting <= 0;
1514            super.reset(canDetach && detachIfReset);
1515            if (mNesting > 0) {
1516                mUpdateTime = mTimeBase.getRealtime(SystemClock.elapsedRealtime() * 1000);
1517            }
1518            mAcquireTime = mTotalTime;
1519            return canDetach;
1520        }
1521
1522        void detach() {
1523            super.detach();
1524            if (mTimerPool != null) {
1525                mTimerPool.remove(this);
1526            }
1527        }
1528
1529        void readSummaryFromParcelLocked(Parcel in) {
1530            super.readSummaryFromParcelLocked(in);
1531            mNesting = 0;
1532        }
1533    }
1534
1535    /*
1536     * Get the wakeup reason counter, and create a new one if one
1537     * doesn't already exist.
1538     */
1539    public LongSamplingCounter getWakeupReasonCounterLocked(String name) {
1540        LongSamplingCounter counter = mWakeupReasonStats.get(name);
1541        if (counter == null) {
1542            counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
1543            mWakeupReasonStats.put(name, counter);
1544        }
1545        return counter;
1546    }
1547
1548    private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
1549
1550        FileInputStream is;
1551        byte[] buffer = new byte[8192];
1552        int len;
1553        boolean wakeup_sources = false;
1554
1555        try {
1556            try {
1557                is = new FileInputStream("/proc/wakelocks");
1558            } catch (java.io.FileNotFoundException e) {
1559                try {
1560                    is = new FileInputStream("/d/wakeup_sources");
1561                    wakeup_sources = true;
1562                } catch (java.io.FileNotFoundException e2) {
1563                    return null;
1564                }
1565            }
1566
1567            len = is.read(buffer);
1568            is.close();
1569        } catch (java.io.IOException e) {
1570            return null;
1571        }
1572
1573        if (len > 0) {
1574            int i;
1575            for (i=0; i<len; i++) {
1576                if (buffer[i] == '\0') {
1577                    len = i;
1578                    break;
1579                }
1580            }
1581        }
1582
1583        return parseProcWakelocks(buffer, len, wakeup_sources);
1584    }
1585
1586    private final Map<String, KernelWakelockStats> parseProcWakelocks(
1587            byte[] wlBuffer, int len, boolean wakeup_sources) {
1588        String name;
1589        int count;
1590        long totalTime;
1591        int startIndex;
1592        int endIndex;
1593        int numUpdatedWlNames = 0;
1594
1595        // Advance past the first line.
1596        int i;
1597        for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
1598        startIndex = endIndex = i + 1;
1599
1600        synchronized(this) {
1601            Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
1602
1603            sKernelWakelockUpdateVersion++;
1604            while (endIndex < len) {
1605                for (endIndex=startIndex;
1606                        endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
1607                        endIndex++);
1608                endIndex++; // endIndex is an exclusive upper bound.
1609                // Don't go over the end of the buffer, Process.parseProcLine might
1610                // write to wlBuffer[endIndex]
1611                if (endIndex >= (len - 1) ) {
1612                    return m;
1613                }
1614
1615                String[] nameStringArray = mProcWakelocksName;
1616                long[] wlData = mProcWakelocksData;
1617                // Stomp out any bad characters since this is from a circular buffer
1618                // A corruption is seen sometimes that results in the vm crashing
1619                // This should prevent crashes and the line will probably fail to parse
1620                for (int j = startIndex; j < endIndex; j++) {
1621                    if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
1622                }
1623                boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
1624                        wakeup_sources ? WAKEUP_SOURCES_FORMAT :
1625                                         PROC_WAKELOCKS_FORMAT,
1626                        nameStringArray, wlData, null);
1627
1628                name = nameStringArray[0];
1629                count = (int) wlData[1];
1630
1631                if (wakeup_sources) {
1632                        // convert milliseconds to microseconds
1633                        totalTime = wlData[2] * 1000;
1634                } else {
1635                        // convert nanoseconds to microseconds with rounding.
1636                        totalTime = (wlData[2] + 500) / 1000;
1637                }
1638
1639                if (parsed && name.length() > 0) {
1640                    if (!m.containsKey(name)) {
1641                        m.put(name, new KernelWakelockStats(count, totalTime,
1642                                sKernelWakelockUpdateVersion));
1643                        numUpdatedWlNames++;
1644                    } else {
1645                        KernelWakelockStats kwlStats = m.get(name);
1646                        if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
1647                            kwlStats.mCount += count;
1648                            kwlStats.mTotalTime += totalTime;
1649                        } else {
1650                            kwlStats.mCount = count;
1651                            kwlStats.mTotalTime = totalTime;
1652                            kwlStats.mVersion = sKernelWakelockUpdateVersion;
1653                            numUpdatedWlNames++;
1654                        }
1655                    }
1656                }
1657                startIndex = endIndex;
1658            }
1659
1660            if (m.size() != numUpdatedWlNames) {
1661                // Don't report old data.
1662                Iterator<KernelWakelockStats> itr = m.values().iterator();
1663                while (itr.hasNext()) {
1664                    if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
1665                        itr.remove();
1666                    }
1667                }
1668            }
1669            return m;
1670        }
1671    }
1672
1673    private class KernelWakelockStats {
1674        public int mCount;
1675        public long mTotalTime;
1676        public int mVersion;
1677
1678        KernelWakelockStats(int count, long totalTime, int version) {
1679            mCount = count;
1680            mTotalTime = totalTime;
1681            mVersion = version;
1682        }
1683    }
1684
1685    /*
1686     * Get the KernelWakelockTimer associated with name, and create a new one if one
1687     * doesn't already exist.
1688     */
1689    public SamplingTimer getKernelWakelockTimerLocked(String name) {
1690        SamplingTimer kwlt = mKernelWakelockStats.get(name);
1691        if (kwlt == null) {
1692            kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, true /* track reported values */);
1693            mKernelWakelockStats.put(name, kwlt);
1694        }
1695        return kwlt;
1696    }
1697
1698    private int getCurrentBluetoothPingCount() {
1699        if (mBtHeadset != null) {
1700            List<BluetoothDevice> deviceList = mBtHeadset.getConnectedDevices();
1701            if (deviceList.size() > 0) {
1702                return mBtHeadset.getBatteryUsageHint(deviceList.get(0));
1703            }
1704        }
1705        return -1;
1706    }
1707
1708    public int getBluetoothPingCount() {
1709        if (mBluetoothPingStart == -1) {
1710            return mBluetoothPingCount;
1711        } else if (mBtHeadset != null) {
1712            return getCurrentBluetoothPingCount() - mBluetoothPingStart;
1713        }
1714        return 0;
1715    }
1716
1717    public void setBtHeadset(BluetoothHeadset headset) {
1718        if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) {
1719            mBluetoothPingStart = getCurrentBluetoothPingCount();
1720        }
1721        mBtHeadset = headset;
1722    }
1723
1724    private int writeHistoryTag(HistoryTag tag) {
1725        Integer idxObj = mHistoryTagPool.get(tag);
1726        int idx;
1727        if (idxObj != null) {
1728            idx = idxObj;
1729        } else {
1730            idx = mNextHistoryTagIdx;
1731            HistoryTag key = new HistoryTag();
1732            key.setTo(tag);
1733            tag.poolIdx = idx;
1734            mHistoryTagPool.put(key, idx);
1735            mNextHistoryTagIdx++;
1736            mNumHistoryTagChars += key.string.length() + 1;
1737        }
1738        return idx;
1739    }
1740
1741    private void readHistoryTag(int index, HistoryTag tag) {
1742        tag.string = mReadHistoryStrings[index];
1743        tag.uid = mReadHistoryUids[index];
1744        tag.poolIdx = index;
1745    }
1746
1747    // Part of initial delta int that specifies the time delta.
1748    static final int DELTA_TIME_MASK = 0x7ffff;
1749    static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
1750    static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
1751    static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
1752    // Flag in delta int: a new battery level int follows.
1753    static final int DELTA_BATTERY_LEVEL_FLAG   = 0x00080000;
1754    // Flag in delta int: a new full state and battery status int follows.
1755    static final int DELTA_STATE_FLAG           = 0x00100000;
1756    // Flag in delta int: a new full state2 int follows.
1757    static final int DELTA_STATE2_FLAG          = 0x00200000;
1758    // Flag in delta int: contains a wakelock or wakeReason tag.
1759    static final int DELTA_WAKELOCK_FLAG        = 0x00400000;
1760    // Flag in delta int: contains an event description.
1761    static final int DELTA_EVENT_FLAG           = 0x00800000;
1762    // These upper bits are the frequently changing state bits.
1763    static final int DELTA_STATE_MASK           = 0xff000000;
1764
1765    // These are the pieces of battery state that are packed in to the upper bits of
1766    // the state int that have been packed in to the first delta int.  They must fit
1767    // in DELTA_STATE_MASK.
1768    static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
1769    static final int STATE_BATTERY_STATUS_SHIFT = 29;
1770    static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
1771    static final int STATE_BATTERY_HEALTH_SHIFT = 26;
1772    static final int STATE_BATTERY_PLUG_MASK    = 0x00000003;
1773    static final int STATE_BATTERY_PLUG_SHIFT   = 24;
1774
1775    public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
1776        if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
1777            dest.writeInt(DELTA_TIME_ABS);
1778            cur.writeToParcel(dest, 0);
1779            return;
1780        }
1781
1782        final long deltaTime = cur.time - last.time;
1783        final int lastBatteryLevelInt = buildBatteryLevelInt(last);
1784        final int lastStateInt = buildStateInt(last);
1785
1786        int deltaTimeToken;
1787        if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
1788            deltaTimeToken = DELTA_TIME_LONG;
1789        } else if (deltaTime >= DELTA_TIME_ABS) {
1790            deltaTimeToken = DELTA_TIME_INT;
1791        } else {
1792            deltaTimeToken = (int)deltaTime;
1793        }
1794        int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
1795        final int batteryLevelInt = buildBatteryLevelInt(cur);
1796        final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
1797        if (batteryLevelIntChanged) {
1798            firstToken |= DELTA_BATTERY_LEVEL_FLAG;
1799        }
1800        final int stateInt = buildStateInt(cur);
1801        final boolean stateIntChanged = stateInt != lastStateInt;
1802        if (stateIntChanged) {
1803            firstToken |= DELTA_STATE_FLAG;
1804        }
1805        final boolean state2IntChanged = cur.states2 != last.states2;
1806        if (state2IntChanged) {
1807            firstToken |= DELTA_STATE2_FLAG;
1808        }
1809        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
1810            firstToken |= DELTA_WAKELOCK_FLAG;
1811        }
1812        if (cur.eventCode != HistoryItem.EVENT_NONE) {
1813            firstToken |= DELTA_EVENT_FLAG;
1814        }
1815        dest.writeInt(firstToken);
1816        if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
1817                + " deltaTime=" + deltaTime);
1818
1819        if (deltaTimeToken >= DELTA_TIME_INT) {
1820            if (deltaTimeToken == DELTA_TIME_INT) {
1821                if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
1822                dest.writeInt((int)deltaTime);
1823            } else {
1824                if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
1825                dest.writeLong(deltaTime);
1826            }
1827        }
1828        if (batteryLevelIntChanged) {
1829            dest.writeInt(batteryLevelInt);
1830            if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
1831                    + Integer.toHexString(batteryLevelInt)
1832                    + " batteryLevel=" + cur.batteryLevel
1833                    + " batteryTemp=" + cur.batteryTemperature
1834                    + " batteryVolt=" + (int)cur.batteryVoltage);
1835        }
1836        if (stateIntChanged) {
1837            dest.writeInt(stateInt);
1838            if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
1839                    + Integer.toHexString(stateInt)
1840                    + " batteryStatus=" + cur.batteryStatus
1841                    + " batteryHealth=" + cur.batteryHealth
1842                    + " batteryPlugType=" + cur.batteryPlugType
1843                    + " states=0x" + Integer.toHexString(cur.states));
1844        }
1845        if (state2IntChanged) {
1846            dest.writeInt(cur.states2);
1847            if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
1848                    + Integer.toHexString(cur.states2));
1849        }
1850        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
1851            int wakeLockIndex;
1852            int wakeReasonIndex;
1853            if (cur.wakelockTag != null) {
1854                wakeLockIndex = writeHistoryTag(cur.wakelockTag);
1855                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
1856                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
1857            } else {
1858                wakeLockIndex = 0xffff;
1859            }
1860            if (cur.wakeReasonTag != null) {
1861                wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
1862                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
1863                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
1864            } else {
1865                wakeReasonIndex = 0xffff;
1866            }
1867            dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
1868        }
1869        if (cur.eventCode != HistoryItem.EVENT_NONE) {
1870            int index = writeHistoryTag(cur.eventTag);
1871            int codeAndIndex = (cur.eventCode&0xffff) | (index<<16);
1872            dest.writeInt(codeAndIndex);
1873            if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
1874                    + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
1875                    + cur.eventTag.string);
1876        }
1877    }
1878
1879    private int buildBatteryLevelInt(HistoryItem h) {
1880        return ((((int)h.batteryLevel)<<25)&0xfe000000)
1881                | ((((int)h.batteryTemperature)<<14)&0x01ffc000)
1882                | (((int)h.batteryVoltage)&0x00003fff);
1883    }
1884
1885    private int buildStateInt(HistoryItem h) {
1886        int plugType = 0;
1887        if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
1888            plugType = 1;
1889        } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
1890            plugType = 2;
1891        } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
1892            plugType = 3;
1893        }
1894        return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
1895                | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
1896                | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
1897                | (h.states&(~DELTA_STATE_MASK));
1898    }
1899
1900    public void readHistoryDelta(Parcel src, HistoryItem cur) {
1901        int firstToken = src.readInt();
1902        int deltaTimeToken = firstToken&DELTA_TIME_MASK;
1903        cur.cmd = HistoryItem.CMD_UPDATE;
1904        cur.numReadInts = 1;
1905        if (DEBUG) Slog.i(TAG, "READ DELTA: firstToken=0x" + Integer.toHexString(firstToken)
1906                + " deltaTimeToken=" + deltaTimeToken);
1907
1908        if (deltaTimeToken < DELTA_TIME_ABS) {
1909            cur.time += deltaTimeToken;
1910        } else if (deltaTimeToken == DELTA_TIME_ABS) {
1911            cur.time = src.readLong();
1912            cur.numReadInts += 2;
1913            if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
1914            cur.readFromParcel(src);
1915            return;
1916        } else if (deltaTimeToken == DELTA_TIME_INT) {
1917            int delta = src.readInt();
1918            cur.time += delta;
1919            cur.numReadInts += 1;
1920            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
1921        } else {
1922            long delta = src.readLong();
1923            if (DEBUG) Slog.i(TAG, "READ DELTA: time delta=" + delta + " new time=" + cur.time);
1924            cur.time += delta;
1925            cur.numReadInts += 2;
1926        }
1927
1928        if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
1929            int batteryLevelInt = src.readInt();
1930            cur.batteryLevel = (byte)((batteryLevelInt>>25)&0x7f);
1931            cur.batteryTemperature = (short)((batteryLevelInt<<7)>>21);
1932            cur.batteryVoltage = (char)(batteryLevelInt&0x3fff);
1933            cur.numReadInts += 1;
1934            if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x"
1935                    + Integer.toHexString(batteryLevelInt)
1936                    + " batteryLevel=" + cur.batteryLevel
1937                    + " batteryTemp=" + cur.batteryTemperature
1938                    + " batteryVolt=" + (int)cur.batteryVoltage);
1939        }
1940
1941        if ((firstToken&DELTA_STATE_FLAG) != 0) {
1942            int stateInt = src.readInt();
1943            cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK));
1944            cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
1945                    & STATE_BATTERY_STATUS_MASK);
1946            cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
1947                    & STATE_BATTERY_HEALTH_MASK);
1948            cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
1949                    & STATE_BATTERY_PLUG_MASK);
1950            switch (cur.batteryPlugType) {
1951                case 1:
1952                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
1953                    break;
1954                case 2:
1955                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
1956                    break;
1957                case 3:
1958                    cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
1959                    break;
1960            }
1961            cur.numReadInts += 1;
1962            if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
1963                    + Integer.toHexString(stateInt)
1964                    + " batteryStatus=" + cur.batteryStatus
1965                    + " batteryHealth=" + cur.batteryHealth
1966                    + " batteryPlugType=" + cur.batteryPlugType
1967                    + " states=0x" + Integer.toHexString(cur.states));
1968        } else {
1969            cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~DELTA_STATE_MASK));
1970        }
1971
1972        if ((firstToken&DELTA_STATE2_FLAG) != 0) {
1973            cur.states2 = src.readInt();
1974            if (DEBUG) Slog.i(TAG, "READ DELTA: states2=0x"
1975                    + Integer.toHexString(cur.states2));
1976        }
1977
1978        if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
1979            int indexes = src.readInt();
1980            int wakeLockIndex = indexes&0xffff;
1981            int wakeReasonIndex = (indexes>>16)&0xffff;
1982            if (wakeLockIndex != 0xffff) {
1983                cur.wakelockTag = cur.localWakelockTag;
1984                readHistoryTag(wakeLockIndex, cur.wakelockTag);
1985                if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
1986                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
1987            } else {
1988                cur.wakelockTag = null;
1989            }
1990            if (wakeReasonIndex != 0xffff) {
1991                cur.wakeReasonTag = cur.localWakeReasonTag;
1992                readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
1993                if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
1994                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
1995            } else {
1996                cur.wakeReasonTag = null;
1997            }
1998            cur.numReadInts += 1;
1999        } else {
2000            cur.wakelockTag = null;
2001            cur.wakeReasonTag = null;
2002        }
2003
2004        if ((firstToken&DELTA_EVENT_FLAG) != 0) {
2005            cur.eventTag = cur.localEventTag;
2006            final int codeAndIndex = src.readInt();
2007            cur.eventCode = (codeAndIndex&0xffff);
2008            final int index = ((codeAndIndex>>16)&0xffff);
2009            readHistoryTag(index, cur.eventTag);
2010            cur.numReadInts += 1;
2011            if (DEBUG) Slog.i(TAG, "READ DELTA: event=" + cur.eventCode + " tag=#"
2012                    + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
2013                    + cur.eventTag.string);
2014        } else {
2015            cur.eventCode = HistoryItem.EVENT_NONE;
2016        }
2017    }
2018
2019    @Override
2020    public void commitCurrentHistoryBatchLocked() {
2021        mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
2022    }
2023
2024    void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
2025        if (!mHaveBatteryLevel || !mRecordingHistory) {
2026            return;
2027        }
2028
2029        final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time;
2030        final int diffStates = mHistoryLastWritten.states^cur.states;
2031        final int diffStates2 = mHistoryLastWritten.states2^cur.states2;
2032        final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
2033        final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
2034        if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff="
2035                + Integer.toHexString(diffStates) + " lastDiff="
2036                + Integer.toHexString(lastDiffStates) + " diff2="
2037                + Integer.toHexString(diffStates2) + " lastDiff2="
2038                + Integer.toHexString(lastDiffStates2));
2039        if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
2040                && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
2041                && (diffStates2&lastDiffStates2) == 0
2042                && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
2043                && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
2044                && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
2045                        || cur.eventCode == HistoryItem.EVENT_NONE)
2046                && mHistoryLastWritten.batteryLevel == cur.batteryLevel
2047                && mHistoryLastWritten.batteryStatus == cur.batteryStatus
2048                && mHistoryLastWritten.batteryHealth == cur.batteryHealth
2049                && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
2050                && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
2051                && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
2052            // We can merge this new change in with the last one.  Merging is
2053            // allowed as long as only the states have changed, and within those states
2054            // as long as no bit has changed both between now and the last entry, as
2055            // well as the last entry and the one before it (so we capture any toggles).
2056            if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
2057            mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
2058            mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
2059            mHistoryBufferLastPos = -1;
2060            elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime;
2061            // If the last written history had a wakelock tag, we need to retain it.
2062            // Note that the condition above made sure that we aren't in a case where
2063            // both it and the current history item have a wakelock tag.
2064            if (mHistoryLastWritten.wakelockTag != null) {
2065                cur.wakelockTag = cur.localWakelockTag;
2066                cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
2067            }
2068            // If the last written history had a wake reason tag, we need to retain it.
2069            // Note that the condition above made sure that we aren't in a case where
2070            // both it and the current history item have a wakelock tag.
2071            if (mHistoryLastWritten.wakeReasonTag != null) {
2072                cur.wakeReasonTag = cur.localWakeReasonTag;
2073                cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
2074            }
2075            // If the last written history had an event, we need to retain it.
2076            // Note that the condition above made sure that we aren't in a case where
2077            // both it and the current history item have an event.
2078            if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
2079                cur.eventCode = mHistoryLastWritten.eventCode;
2080                cur.eventTag = cur.localEventTag;
2081                cur.eventTag.setTo(mHistoryLastWritten.eventTag);
2082            }
2083            mHistoryLastWritten.setTo(mHistoryLastLastWritten);
2084        }
2085
2086        final int dataSize = mHistoryBuffer.dataSize();
2087        if (dataSize >= MAX_HISTORY_BUFFER) {
2088            if (!mHistoryOverflow) {
2089                mHistoryOverflow = true;
2090                addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
2091                addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_OVERFLOW, cur);
2092                return;
2093            }
2094
2095            // Once we've reached the maximum number of items, we only
2096            // record changes to the battery level and the most interesting states.
2097            // Once we've reached the maximum maximum number of items, we only
2098            // record changes to the battery level.
2099            if (mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
2100                    (dataSize >= MAX_MAX_HISTORY_BUFFER
2101                            || ((mHistoryLastWritten.states^cur.states)
2102                                    & HistoryItem.MOST_INTERESTING_STATES) == 0
2103                            || ((mHistoryLastWritten.states2^cur.states2)
2104                                    & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
2105                return;
2106            }
2107
2108            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
2109            return;
2110        }
2111
2112        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
2113    }
2114
2115    private void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd,
2116            HistoryItem cur) {
2117        if (mIteratingHistory) {
2118            throw new IllegalStateException("Can't do this while iterating history!");
2119        }
2120        mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
2121        mHistoryLastLastWritten.setTo(mHistoryLastWritten);
2122        mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
2123        writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
2124        mLastHistoryElapsedRealtime = elapsedRealtimeMs;
2125        cur.wakelockTag = null;
2126        cur.wakeReasonTag = null;
2127        cur.eventCode = HistoryItem.EVENT_NONE;
2128        cur.eventTag = null;
2129        if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
2130                + " now " + mHistoryBuffer.dataPosition()
2131                + " size is now " + mHistoryBuffer.dataSize());
2132    }
2133
2134    int mChangedStates = 0;
2135    int mChangedStates2 = 0;
2136
2137    void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) {
2138        if (mTrackRunningHistoryElapsedRealtime != 0) {
2139            final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime;
2140            final long diffUptime = uptimeMs - mTrackRunningHistoryUptime;
2141            if (diffUptime < (diffElapsed-20)) {
2142                final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime);
2143                mHistoryAddTmp.setTo(mHistoryLastWritten);
2144                mHistoryAddTmp.wakelockTag = null;
2145                mHistoryAddTmp.wakeReasonTag = null;
2146                mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
2147                mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
2148                addHistoryRecordInnerLocked(wakeElapsedTime, uptimeMs, mHistoryAddTmp);
2149            }
2150        }
2151        mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
2152        mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs;
2153        mTrackRunningHistoryUptime = uptimeMs;
2154        addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur);
2155    }
2156
2157    void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
2158        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur);
2159
2160        if (!USE_OLD_HISTORY) {
2161            return;
2162        }
2163
2164        if (!mHaveBatteryLevel || !mRecordingHistory) {
2165            return;
2166        }
2167
2168        // If the current time is basically the same as the last time,
2169        // and no states have since the last recorded entry changed and
2170        // are now resetting back to their original value, then just collapse
2171        // into one record.
2172        if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
2173                && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000)
2174                && ((mHistoryEnd.states^cur.states)&mChangedStates) == 0
2175                && ((mHistoryEnd.states2^cur.states2)&mChangedStates2) == 0) {
2176            // If the current is the same as the one before, then we no
2177            // longer need the entry.
2178            if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
2179                    && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500)
2180                    && mHistoryLastEnd.sameNonEvent(cur)) {
2181                mHistoryLastEnd.next = null;
2182                mHistoryEnd.next = mHistoryCache;
2183                mHistoryCache = mHistoryEnd;
2184                mHistoryEnd = mHistoryLastEnd;
2185                mHistoryLastEnd = null;
2186            } else {
2187                mChangedStates |= mHistoryEnd.states^cur.states;
2188                mChangedStates2 |= mHistoryEnd.states^cur.states2;
2189                mHistoryEnd.setTo(mHistoryEnd.time, HistoryItem.CMD_UPDATE, cur);
2190            }
2191            return;
2192        }
2193
2194        mChangedStates = 0;
2195        mChangedStates2 = 0;
2196
2197        if (mNumHistoryItems == MAX_HISTORY_ITEMS
2198                || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
2199            addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW);
2200        }
2201
2202        if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
2203            // Once we've reached the maximum number of items, we only
2204            // record changes to the battery level and the most interesting states.
2205            // Once we've reached the maximum maximum number of items, we only
2206            // record changes to the battery level.
2207            if (mHistoryEnd != null && mHistoryEnd.batteryLevel
2208                    == cur.batteryLevel &&
2209                    (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
2210                            || ((mHistoryEnd.states^cur.states)
2211                                    & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
2212                return;
2213            }
2214        }
2215
2216        addHistoryRecordLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE);
2217    }
2218
2219    void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code,
2220            String name, int uid) {
2221        mHistoryCur.eventCode = code;
2222        mHistoryCur.eventTag = mHistoryCur.localEventTag;
2223        mHistoryCur.eventTag.string = name;
2224        mHistoryCur.eventTag.uid = uid;
2225        addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
2226    }
2227
2228    void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) {
2229        HistoryItem rec = mHistoryCache;
2230        if (rec != null) {
2231            mHistoryCache = rec.next;
2232        } else {
2233            rec = new HistoryItem();
2234        }
2235        rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur);
2236
2237        addHistoryRecordLocked(rec);
2238    }
2239
2240    void addHistoryRecordLocked(HistoryItem rec) {
2241        mNumHistoryItems++;
2242        rec.next = null;
2243        mHistoryLastEnd = mHistoryEnd;
2244        if (mHistoryEnd != null) {
2245            mHistoryEnd.next = rec;
2246            mHistoryEnd = rec;
2247        } else {
2248            mHistory = mHistoryEnd = rec;
2249        }
2250    }
2251
2252    void clearHistoryLocked() {
2253        if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
2254        if (USE_OLD_HISTORY) {
2255            if (mHistory != null) {
2256                mHistoryEnd.next = mHistoryCache;
2257                mHistoryCache = mHistory;
2258                mHistory = mHistoryLastEnd = mHistoryEnd = null;
2259            }
2260            mNumHistoryItems = 0;
2261        }
2262
2263        mHistoryBaseTime = 0;
2264        mLastHistoryElapsedRealtime = 0;
2265        mTrackRunningHistoryElapsedRealtime = 0;
2266        mTrackRunningHistoryUptime = 0;
2267
2268        mHistoryBuffer.setDataSize(0);
2269        mHistoryBuffer.setDataPosition(0);
2270        mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
2271        mHistoryLastLastWritten.clear();
2272        mHistoryLastWritten.clear();
2273        mHistoryTagPool.clear();
2274        mNextHistoryTagIdx = 0;
2275        mNumHistoryTagChars = 0;
2276        mHistoryBufferLastPos = -1;
2277        mHistoryOverflow = false;
2278    }
2279
2280    public void updateTimeBasesLocked(boolean unplugged, boolean screenOff, long uptime,
2281            long realtime) {
2282        if (mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime)) {
2283            if (unplugged) {
2284                // Track bt headset ping count
2285                mBluetoothPingStart = getCurrentBluetoothPingCount();
2286                mBluetoothPingCount = 0;
2287            } else {
2288                // Track bt headset ping count
2289                mBluetoothPingCount = getBluetoothPingCount();
2290                mBluetoothPingStart = -1;
2291            }
2292        }
2293
2294        boolean unpluggedScreenOff = unplugged && screenOff;
2295        if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
2296            updateKernelWakelocksLocked();
2297            requestWakelockCpuUpdate();
2298            if (!unpluggedScreenOff) {
2299                // We are switching to no longer tracking wake locks, but we want
2300                // the next CPU update we receive to take them in to account.
2301                mDistributeWakelockCpu = true;
2302            }
2303            mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
2304        }
2305    }
2306
2307    public void addIsolatedUidLocked(int isolatedUid, int appUid) {
2308        mIsolatedUids.put(isolatedUid, appUid);
2309    }
2310
2311    public void removeIsolatedUidLocked(int isolatedUid, int appUid) {
2312        int curUid = mIsolatedUids.get(isolatedUid, -1);
2313        if (curUid == appUid) {
2314            mIsolatedUids.delete(isolatedUid);
2315        }
2316    }
2317
2318    public int mapUid(int uid) {
2319        int isolated = mIsolatedUids.get(uid, -1);
2320        return isolated > 0 ? isolated : uid;
2321    }
2322
2323    public void noteEventLocked(int code, String name, int uid) {
2324        uid = mapUid(uid);
2325        if (!mActiveEvents.updateState(code, name, uid, 0)) {
2326            return;
2327        }
2328        final long elapsedRealtime = SystemClock.elapsedRealtime();
2329        final long uptime = SystemClock.uptimeMillis();
2330        addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
2331    }
2332
2333    public void noteProcessStartLocked(String name, int uid) {
2334        uid = mapUid(uid);
2335        if (isOnBattery()) {
2336            Uid u = getUidStatsLocked(uid);
2337            u.getProcessStatsLocked(name).incStartsLocked();
2338        }
2339        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
2340            return;
2341        }
2342        final long elapsedRealtime = SystemClock.elapsedRealtime();
2343        final long uptime = SystemClock.uptimeMillis();
2344        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
2345    }
2346
2347    public void noteProcessStateLocked(String name, int uid, int state) {
2348        uid = mapUid(uid);
2349        final long elapsedRealtime = SystemClock.elapsedRealtime();
2350        getUidStatsLocked(uid).updateProcessStateLocked(name, state, elapsedRealtime);
2351    }
2352
2353    public void noteProcessFinishLocked(String name, int uid) {
2354        uid = mapUid(uid);
2355        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
2356            return;
2357        }
2358        final long elapsedRealtime = SystemClock.elapsedRealtime();
2359        final long uptime = SystemClock.uptimeMillis();
2360        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
2361        getUidStatsLocked(uid).updateProcessStateLocked(name, Uid.PROCESS_STATE_NONE,
2362                elapsedRealtime);
2363    }
2364
2365    private void requestWakelockCpuUpdate() {
2366        if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
2367            Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
2368            mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
2369        }
2370    }
2371
2372    public void setRecordAllWakeLocksLocked(boolean enabled) {
2373        mRecordAllWakeLocks = enabled;
2374        if (!enabled) {
2375            // Clear out any existing state.
2376            mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
2377        }
2378    }
2379
2380    public void setNoAutoReset(boolean enabled) {
2381        mNoAutoReset = enabled;
2382    }
2383
2384    private String mInitialAcquireWakeName;
2385    private int mInitialAcquireWakeUid = -1;
2386
2387    public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
2388            boolean unimportantForLogging, long elapsedRealtime, long uptime) {
2389        uid = mapUid(uid);
2390        if (type == WAKE_TYPE_PARTIAL) {
2391            // Only care about partial wake locks, since full wake locks
2392            // will be canceled when the user puts the screen to sleep.
2393            aggregateLastWakeupUptimeLocked(uptime);
2394            if (historyName == null) {
2395                historyName = name;
2396            }
2397            if (mRecordAllWakeLocks) {
2398                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
2399                        uid, 0)) {
2400                    addHistoryEventLocked(elapsedRealtime, uptime,
2401                            HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
2402                }
2403            }
2404            if (mWakeLockNesting == 0) {
2405                mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
2406                if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
2407                        + Integer.toHexString(mHistoryCur.states));
2408                mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
2409                mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
2410                mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
2411                mWakeLockImportant = !unimportantForLogging;
2412                addHistoryRecordLocked(elapsedRealtime, uptime);
2413            } else if (!mWakeLockImportant && !unimportantForLogging
2414                    && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
2415                if (mHistoryLastWritten.wakelockTag != null) {
2416                    // We'll try to update the last tag.
2417                    mHistoryLastWritten.wakelockTag = null;
2418                    mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
2419                    mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
2420                    mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
2421                    addHistoryRecordLocked(elapsedRealtime, uptime);
2422                }
2423                mWakeLockImportant = true;
2424            }
2425            mWakeLockNesting++;
2426        }
2427        if (uid >= 0) {
2428            //if (uid == 0) {
2429            //    Slog.wtf(TAG, "Acquiring wake lock from root: " + name);
2430            //}
2431            requestWakelockCpuUpdate();
2432            getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
2433        }
2434    }
2435
2436    public void noteStopWakeLocked(int uid, int pid, String name, String historyName, int type,
2437            long elapsedRealtime, long uptime) {
2438        uid = mapUid(uid);
2439        if (type == WAKE_TYPE_PARTIAL) {
2440            mWakeLockNesting--;
2441            if (mRecordAllWakeLocks) {
2442                if (historyName == null) {
2443                    historyName = name;
2444                }
2445                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
2446                        uid, 0)) {
2447                    addHistoryEventLocked(elapsedRealtime, uptime,
2448                            HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
2449                }
2450            }
2451            if (mWakeLockNesting == 0) {
2452                mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
2453                if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
2454                        + Integer.toHexString(mHistoryCur.states));
2455                mInitialAcquireWakeName = null;
2456                mInitialAcquireWakeUid = -1;
2457                addHistoryRecordLocked(elapsedRealtime, uptime);
2458            }
2459        }
2460        if (uid >= 0) {
2461            requestWakelockCpuUpdate();
2462            getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
2463        }
2464    }
2465
2466    public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
2467            String historyName, int type, boolean unimportantForLogging) {
2468        final long elapsedRealtime = SystemClock.elapsedRealtime();
2469        final long uptime = SystemClock.uptimeMillis();
2470        final int N = ws.size();
2471        for (int i=0; i<N; i++) {
2472            noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
2473                    elapsedRealtime, uptime);
2474        }
2475    }
2476
2477    public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
2478            String historyName, int type, WorkSource newWs, int newPid, String newName,
2479            String newHistoryName, int newType, boolean newUnimportantForLogging) {
2480        final long elapsedRealtime = SystemClock.elapsedRealtime();
2481        final long uptime = SystemClock.uptimeMillis();
2482        // For correct semantics, we start the need worksources first, so that we won't
2483        // make inappropriate history items as if all wake locks went away and new ones
2484        // appeared.  This is okay because tracking of wake locks allows nesting.
2485        final int NN = newWs.size();
2486        for (int i=0; i<NN; i++) {
2487            noteStartWakeLocked(newWs.get(i), newPid, newName, newHistoryName, newType,
2488                    newUnimportantForLogging, elapsedRealtime, uptime);
2489        }
2490        final int NO = ws.size();
2491        for (int i=0; i<NO; i++) {
2492            noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
2493        }
2494    }
2495
2496    public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
2497            String historyName, int type) {
2498        final long elapsedRealtime = SystemClock.elapsedRealtime();
2499        final long uptime = SystemClock.uptimeMillis();
2500        final int N = ws.size();
2501        for (int i=0; i<N; i++) {
2502            noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
2503        }
2504    }
2505
2506    void aggregateLastWakeupUptimeLocked(long uptimeMs) {
2507        if (mLastWakeupReason != null) {
2508            long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
2509            LongSamplingCounter timer = getWakeupReasonCounterLocked(mLastWakeupReason);
2510            timer.addCountLocked(deltaUptime);
2511            mLastWakeupReason = null;
2512        }
2513    }
2514
2515    public void noteWakeupReasonLocked(String reason) {
2516        final long elapsedRealtime = SystemClock.elapsedRealtime();
2517        final long uptime = SystemClock.uptimeMillis();
2518        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason reason \"" + reason +"\": "
2519                + Integer.toHexString(mHistoryCur.states));
2520        aggregateLastWakeupUptimeLocked(uptime);
2521        mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
2522        mHistoryCur.wakeReasonTag.string = reason;
2523        mHistoryCur.wakeReasonTag.uid = 0;
2524        mLastWakeupReason = reason;
2525        mLastWakeupUptimeMs = uptime;
2526        addHistoryRecordLocked(elapsedRealtime, uptime);
2527    }
2528
2529    public int startAddingCpuLocked() {
2530        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
2531
2532        final int N = mPartialTimers.size();
2533        if (N == 0) {
2534            mLastPartialTimers.clear();
2535            mDistributeWakelockCpu = false;
2536            return 0;
2537        }
2538
2539        if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) {
2540            return 0;
2541        }
2542
2543        mDistributeWakelockCpu = false;
2544
2545        // How many timers should consume CPU?  Only want to include ones
2546        // that have already been in the list.
2547        for (int i=0; i<N; i++) {
2548            StopwatchTimer st = mPartialTimers.get(i);
2549            if (st.mInList) {
2550                Uid uid = st.mUid;
2551                // We don't include the system UID, because it so often
2552                // holds wake locks at one request or another of an app.
2553                if (uid != null && uid.mUid != Process.SYSTEM_UID) {
2554                    return 50;
2555                }
2556            }
2557        }
2558
2559        return 0;
2560    }
2561
2562    public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
2563        final int N = mPartialTimers.size();
2564        if (perc != 0) {
2565            int num = 0;
2566            for (int i=0; i<N; i++) {
2567                StopwatchTimer st = mPartialTimers.get(i);
2568                if (st.mInList) {
2569                    Uid uid = st.mUid;
2570                    // We don't include the system UID, because it so often
2571                    // holds wake locks at one request or another of an app.
2572                    if (uid != null && uid.mUid != Process.SYSTEM_UID) {
2573                        num++;
2574                    }
2575                }
2576            }
2577            if (num != 0) {
2578                for (int i=0; i<N; i++) {
2579                    StopwatchTimer st = mPartialTimers.get(i);
2580                    if (st.mInList) {
2581                        Uid uid = st.mUid;
2582                        if (uid != null && uid.mUid != Process.SYSTEM_UID) {
2583                            int myUTime = utime/num;
2584                            int mySTime = stime/num;
2585                            utime -= myUTime;
2586                            stime -= mySTime;
2587                            num--;
2588                            Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
2589                            proc.addCpuTimeLocked(myUTime, mySTime);
2590                            proc.addSpeedStepTimes(cpuSpeedTimes);
2591                        }
2592                    }
2593                }
2594            }
2595
2596            // Just in case, collect any lost CPU time.
2597            if (utime != 0 || stime != 0) {
2598                Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
2599                if (uid != null) {
2600                    Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
2601                    proc.addCpuTimeLocked(utime, stime);
2602                    proc.addSpeedStepTimes(cpuSpeedTimes);
2603                }
2604            }
2605        }
2606
2607        final int NL = mLastPartialTimers.size();
2608        boolean diff = N != NL;
2609        for (int i=0; i<NL && !diff; i++) {
2610            diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
2611        }
2612        if (!diff) {
2613            for (int i=0; i<NL; i++) {
2614                mPartialTimers.get(i).mInList = true;
2615            }
2616            return;
2617        }
2618
2619        for (int i=0; i<NL; i++) {
2620            mLastPartialTimers.get(i).mInList = false;
2621        }
2622        mLastPartialTimers.clear();
2623        for (int i=0; i<N; i++) {
2624            StopwatchTimer st = mPartialTimers.get(i);
2625            st.mInList = true;
2626            mLastPartialTimers.add(st);
2627        }
2628    }
2629
2630    public void noteProcessDiedLocked(int uid, int pid) {
2631        uid = mapUid(uid);
2632        Uid u = mUidStats.get(uid);
2633        if (u != null) {
2634            u.mPids.remove(pid);
2635        }
2636    }
2637
2638    public long getProcessWakeTime(int uid, int pid, long realtime) {
2639        uid = mapUid(uid);
2640        Uid u = mUidStats.get(uid);
2641        if (u != null) {
2642            Uid.Pid p = u.mPids.get(pid);
2643            if (p != null) {
2644                return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
2645            }
2646        }
2647        return 0;
2648    }
2649
2650    public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) {
2651        uid = mapUid(uid);
2652        Uid u = mUidStats.get(uid);
2653        if (u != null) {
2654            u.reportExcessiveWakeLocked(proc, overTime, usedTime);
2655        }
2656    }
2657
2658    public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
2659        uid = mapUid(uid);
2660        Uid u = mUidStats.get(uid);
2661        if (u != null) {
2662            u.reportExcessiveCpuLocked(proc, overTime, usedTime);
2663        }
2664    }
2665
2666    int mSensorNesting;
2667
2668    public void noteStartSensorLocked(int uid, int sensor) {
2669        uid = mapUid(uid);
2670        final long elapsedRealtime = SystemClock.elapsedRealtime();
2671        final long uptime = SystemClock.uptimeMillis();
2672        if (mSensorNesting == 0) {
2673            mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
2674            if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
2675                    + Integer.toHexString(mHistoryCur.states));
2676            addHistoryRecordLocked(elapsedRealtime, uptime);
2677        }
2678        mSensorNesting++;
2679        getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
2680    }
2681
2682    public void noteStopSensorLocked(int uid, int sensor) {
2683        uid = mapUid(uid);
2684        final long elapsedRealtime = SystemClock.elapsedRealtime();
2685        final long uptime = SystemClock.uptimeMillis();
2686        mSensorNesting--;
2687        if (mSensorNesting == 0) {
2688            mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
2689            if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
2690                    + Integer.toHexString(mHistoryCur.states));
2691            addHistoryRecordLocked(elapsedRealtime, uptime);
2692        }
2693        getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
2694    }
2695
2696    int mGpsNesting;
2697
2698    public void noteStartGpsLocked(int uid) {
2699        uid = mapUid(uid);
2700        final long elapsedRealtime = SystemClock.elapsedRealtime();
2701        final long uptime = SystemClock.uptimeMillis();
2702        if (mGpsNesting == 0) {
2703            mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
2704            if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
2705                    + Integer.toHexString(mHistoryCur.states));
2706            addHistoryRecordLocked(elapsedRealtime, uptime);
2707        }
2708        mGpsNesting++;
2709        getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
2710    }
2711
2712    public void noteStopGpsLocked(int uid) {
2713        uid = mapUid(uid);
2714        final long elapsedRealtime = SystemClock.elapsedRealtime();
2715        final long uptime = SystemClock.uptimeMillis();
2716        mGpsNesting--;
2717        if (mGpsNesting == 0) {
2718            mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
2719            if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
2720                    + Integer.toHexString(mHistoryCur.states));
2721            addHistoryRecordLocked(elapsedRealtime, uptime);
2722        }
2723        getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
2724    }
2725
2726    public void noteScreenStateLocked(int state) {
2727        if (mScreenState != state) {
2728            final int oldState = mScreenState;
2729            mScreenState = state;
2730            if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
2731                    + ", newState=" + Display.stateToString(state));
2732
2733            if (state == Display.STATE_ON) {
2734                // Screen turning on.
2735                final long elapsedRealtime = SystemClock.elapsedRealtime();
2736                final long uptime = SystemClock.uptimeMillis();
2737                mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
2738                if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
2739                        + Integer.toHexString(mHistoryCur.states));
2740                addHistoryRecordLocked(elapsedRealtime, uptime);
2741                mScreenOnTimer.startRunningLocked(elapsedRealtime);
2742                if (mScreenBrightnessBin >= 0) {
2743                    mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
2744                }
2745
2746                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
2747                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
2748
2749                // Fake a wake lock, so we consider the device waked as long
2750                // as the screen is on.
2751                noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
2752                        elapsedRealtime, uptime);
2753
2754                // Update discharge amounts.
2755                if (mOnBatteryInternal) {
2756                    updateDischargeScreenLevelsLocked(false, true);
2757                }
2758            } else if (oldState == Display.STATE_ON) {
2759                // Screen turning off or dozing.
2760                final long elapsedRealtime = SystemClock.elapsedRealtime();
2761                final long uptime = SystemClock.uptimeMillis();
2762                mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
2763                if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
2764                        + Integer.toHexString(mHistoryCur.states));
2765                addHistoryRecordLocked(elapsedRealtime, uptime);
2766                mScreenOnTimer.stopRunningLocked(elapsedRealtime);
2767                if (mScreenBrightnessBin >= 0) {
2768                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
2769                }
2770
2771                noteStopWakeLocked(-1, -1, "screen", "screen", WAKE_TYPE_PARTIAL,
2772                        elapsedRealtime, uptime);
2773
2774                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
2775                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
2776
2777                // Update discharge amounts.
2778                if (mOnBatteryInternal) {
2779                    updateDischargeScreenLevelsLocked(true, false);
2780                }
2781            }
2782        }
2783    }
2784
2785    public void noteScreenBrightnessLocked(int brightness) {
2786        // Bin the brightness.
2787        int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
2788        if (bin < 0) bin = 0;
2789        else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
2790        if (mScreenBrightnessBin != bin) {
2791            final long elapsedRealtime = SystemClock.elapsedRealtime();
2792            final long uptime = SystemClock.uptimeMillis();
2793            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
2794                    | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
2795            if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
2796                    + Integer.toHexString(mHistoryCur.states));
2797            addHistoryRecordLocked(elapsedRealtime, uptime);
2798            if (mScreenState == Display.STATE_ON) {
2799                if (mScreenBrightnessBin >= 0) {
2800                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
2801                }
2802                mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
2803            }
2804            mScreenBrightnessBin = bin;
2805        }
2806    }
2807
2808    public void noteUserActivityLocked(int uid, int event) {
2809        if (mOnBatteryInternal) {
2810            uid = mapUid(uid);
2811            getUidStatsLocked(uid).noteUserActivityLocked(event);
2812        }
2813    }
2814
2815    public void noteInteractiveLocked(boolean interactive) {
2816        if (mInteractive != interactive) {
2817            final long elapsedRealtime = SystemClock.elapsedRealtime();
2818            mInteractive = interactive;
2819            if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
2820            if (interactive) {
2821                mInteractiveTimer.startRunningLocked(elapsedRealtime);
2822            } else {
2823                mInteractiveTimer.stopRunningLocked(elapsedRealtime);
2824            }
2825        }
2826    }
2827
2828    public void noteMobileRadioPowerState(int powerState, long timestampNs) {
2829        final long elapsedRealtime = SystemClock.elapsedRealtime();
2830        final long uptime = SystemClock.uptimeMillis();
2831        if (mMobileRadioPowerState != powerState) {
2832            long realElapsedRealtimeMs;
2833            final boolean active =
2834                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
2835                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
2836            if (active) {
2837                mMobileRadioActiveStartTime = realElapsedRealtimeMs = elapsedRealtime;
2838                mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
2839            } else {
2840                realElapsedRealtimeMs = timestampNs / (1000*1000);
2841                long lastUpdateTimeMs = mMobileRadioActiveStartTime;
2842                if (realElapsedRealtimeMs < lastUpdateTimeMs) {
2843                    Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
2844                            + " is before start time " + lastUpdateTimeMs);
2845                    realElapsedRealtimeMs = elapsedRealtime;
2846                } else if (realElapsedRealtimeMs < elapsedRealtime) {
2847                    mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
2848                            - realElapsedRealtimeMs);
2849                }
2850                mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
2851            }
2852            if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
2853                    + Integer.toHexString(mHistoryCur.states));
2854            addHistoryRecordLocked(elapsedRealtime, uptime);
2855            mMobileRadioPowerState = powerState;
2856            if (active) {
2857                mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
2858                mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
2859            } else {
2860                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
2861                updateNetworkActivityLocked(NET_UPDATE_MOBILE, realElapsedRealtimeMs);
2862                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
2863            }
2864        }
2865    }
2866
2867    public void noteLowPowerMode(boolean enabled) {
2868        if (mLowPowerModeEnabled != enabled) {
2869            final long elapsedRealtime = SystemClock.elapsedRealtime();
2870            final long uptime = SystemClock.uptimeMillis();
2871            mLowPowerModeEnabled = enabled;
2872            if (enabled) {
2873                mHistoryCur.states2 |= HistoryItem.STATE2_LOW_POWER_FLAG;
2874                if (DEBUG_HISTORY) Slog.v(TAG, "Low power mode enabled to: "
2875                        + Integer.toHexString(mHistoryCur.states2));
2876                mLowPowerModeEnabledTimer.startRunningLocked(elapsedRealtime);
2877            } else {
2878                mHistoryCur.states2 &= ~HistoryItem.STATE2_LOW_POWER_FLAG;
2879                if (DEBUG_HISTORY) Slog.v(TAG, "Low power mode disabled to: "
2880                        + Integer.toHexString(mHistoryCur.states2));
2881                mLowPowerModeEnabledTimer.stopRunningLocked(elapsedRealtime);
2882            }
2883            addHistoryRecordLocked(elapsedRealtime, uptime);
2884        }
2885    }
2886
2887    public void notePhoneOnLocked() {
2888        if (!mPhoneOn) {
2889            final long elapsedRealtime = SystemClock.elapsedRealtime();
2890            final long uptime = SystemClock.uptimeMillis();
2891            mHistoryCur.states |= HistoryItem.STATE_PHONE_IN_CALL_FLAG;
2892            if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
2893                    + Integer.toHexString(mHistoryCur.states));
2894            addHistoryRecordLocked(elapsedRealtime, uptime);
2895            mPhoneOn = true;
2896            mPhoneOnTimer.startRunningLocked(elapsedRealtime);
2897        }
2898    }
2899
2900    public void notePhoneOffLocked() {
2901        if (mPhoneOn) {
2902            final long elapsedRealtime = SystemClock.elapsedRealtime();
2903            final long uptime = SystemClock.uptimeMillis();
2904            mHistoryCur.states &= ~HistoryItem.STATE_PHONE_IN_CALL_FLAG;
2905            if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
2906                    + Integer.toHexString(mHistoryCur.states));
2907            addHistoryRecordLocked(elapsedRealtime, uptime);
2908            mPhoneOn = false;
2909            mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
2910        }
2911    }
2912
2913    void stopAllPhoneSignalStrengthTimersLocked(int except) {
2914        final long elapsedRealtime = SystemClock.elapsedRealtime();
2915        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
2916            if (i == except) {
2917                continue;
2918            }
2919            while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
2920                mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
2921            }
2922        }
2923    }
2924
2925    private int fixPhoneServiceState(int state, int signalBin) {
2926        if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
2927            // In this case we will always be STATE_OUT_OF_SERVICE, so need
2928            // to infer that we are scanning from other data.
2929            if (state == ServiceState.STATE_OUT_OF_SERVICE
2930                    && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
2931                state = ServiceState.STATE_IN_SERVICE;
2932            }
2933        }
2934
2935        return state;
2936    }
2937
2938    private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
2939        boolean scanning = false;
2940        boolean newHistory = false;
2941
2942        mPhoneServiceStateRaw = state;
2943        mPhoneSimStateRaw = simState;
2944        mPhoneSignalStrengthBinRaw = strengthBin;
2945
2946        final long elapsedRealtime = SystemClock.elapsedRealtime();
2947        final long uptime = SystemClock.uptimeMillis();
2948
2949        if (simState == TelephonyManager.SIM_STATE_ABSENT) {
2950            // In this case we will always be STATE_OUT_OF_SERVICE, so need
2951            // to infer that we are scanning from other data.
2952            if (state == ServiceState.STATE_OUT_OF_SERVICE
2953                    && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
2954                state = ServiceState.STATE_IN_SERVICE;
2955            }
2956        }
2957
2958        // If the phone is powered off, stop all timers.
2959        if (state == ServiceState.STATE_POWER_OFF) {
2960            strengthBin = -1;
2961
2962        // If we are in service, make sure the correct signal string timer is running.
2963        } else if (state == ServiceState.STATE_IN_SERVICE) {
2964            // Bin will be changed below.
2965
2966        // If we're out of service, we are in the lowest signal strength
2967        // bin and have the scanning bit set.
2968        } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
2969            scanning = true;
2970            strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
2971            if (!mPhoneSignalScanningTimer.isRunningLocked()) {
2972                mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
2973                newHistory = true;
2974                if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
2975                        + Integer.toHexString(mHistoryCur.states));
2976                mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
2977            }
2978        }
2979
2980        if (!scanning) {
2981            // If we are no longer scanning, then stop the scanning timer.
2982            if (mPhoneSignalScanningTimer.isRunningLocked()) {
2983                mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
2984                if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
2985                        + Integer.toHexString(mHistoryCur.states));
2986                newHistory = true;
2987                mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
2988            }
2989        }
2990
2991        if (mPhoneServiceState != state) {
2992            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
2993                    | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
2994            if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
2995                    + Integer.toHexString(mHistoryCur.states));
2996            newHistory = true;
2997            mPhoneServiceState = state;
2998        }
2999
3000        if (mPhoneSignalStrengthBin != strengthBin) {
3001            if (mPhoneSignalStrengthBin >= 0) {
3002                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
3003                        elapsedRealtime);
3004            }
3005            if (strengthBin >= 0) {
3006                if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
3007                    mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
3008                }
3009                mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
3010                        | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
3011                if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
3012                        + Integer.toHexString(mHistoryCur.states));
3013                newHistory = true;
3014            } else {
3015                stopAllPhoneSignalStrengthTimersLocked(-1);
3016            }
3017            mPhoneSignalStrengthBin = strengthBin;
3018        }
3019
3020        if (newHistory) {
3021            addHistoryRecordLocked(elapsedRealtime, uptime);
3022        }
3023    }
3024
3025    /**
3026     * Telephony stack updates the phone state.
3027     * @param state phone state from ServiceState.getState()
3028     */
3029    public void notePhoneStateLocked(int state, int simState) {
3030        updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
3031    }
3032
3033    public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
3034        // Bin the strength.
3035        int bin = signalStrength.getLevel();
3036        updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
3037    }
3038
3039    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
3040        int bin = DATA_CONNECTION_NONE;
3041        if (hasData) {
3042            switch (dataType) {
3043                case TelephonyManager.NETWORK_TYPE_EDGE:
3044                    bin = DATA_CONNECTION_EDGE;
3045                    break;
3046                case TelephonyManager.NETWORK_TYPE_GPRS:
3047                    bin = DATA_CONNECTION_GPRS;
3048                    break;
3049                case TelephonyManager.NETWORK_TYPE_UMTS:
3050                    bin = DATA_CONNECTION_UMTS;
3051                    break;
3052                case TelephonyManager.NETWORK_TYPE_CDMA:
3053                    bin = DATA_CONNECTION_CDMA;
3054                    break;
3055                case TelephonyManager.NETWORK_TYPE_EVDO_0:
3056                    bin = DATA_CONNECTION_EVDO_0;
3057                    break;
3058                case TelephonyManager.NETWORK_TYPE_EVDO_A:
3059                    bin = DATA_CONNECTION_EVDO_A;
3060                    break;
3061                case TelephonyManager.NETWORK_TYPE_1xRTT:
3062                    bin = DATA_CONNECTION_1xRTT;
3063                    break;
3064                case TelephonyManager.NETWORK_TYPE_HSDPA:
3065                    bin = DATA_CONNECTION_HSDPA;
3066                    break;
3067                case TelephonyManager.NETWORK_TYPE_HSUPA:
3068                    bin = DATA_CONNECTION_HSUPA;
3069                    break;
3070                case TelephonyManager.NETWORK_TYPE_HSPA:
3071                    bin = DATA_CONNECTION_HSPA;
3072                    break;
3073                case TelephonyManager.NETWORK_TYPE_IDEN:
3074                    bin = DATA_CONNECTION_IDEN;
3075                    break;
3076                case TelephonyManager.NETWORK_TYPE_EVDO_B:
3077                    bin = DATA_CONNECTION_EVDO_B;
3078                    break;
3079                case TelephonyManager.NETWORK_TYPE_LTE:
3080                    bin = DATA_CONNECTION_LTE;
3081                    break;
3082                case TelephonyManager.NETWORK_TYPE_EHRPD:
3083                    bin = DATA_CONNECTION_EHRPD;
3084                    break;
3085                case TelephonyManager.NETWORK_TYPE_HSPAP:
3086                    bin = DATA_CONNECTION_HSPAP;
3087                    break;
3088                default:
3089                    bin = DATA_CONNECTION_OTHER;
3090                    break;
3091            }
3092        }
3093        if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
3094        if (mPhoneDataConnectionType != bin) {
3095            final long elapsedRealtime = SystemClock.elapsedRealtime();
3096            final long uptime = SystemClock.uptimeMillis();
3097            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
3098                    | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
3099            if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
3100                    + Integer.toHexString(mHistoryCur.states));
3101            addHistoryRecordLocked(elapsedRealtime, uptime);
3102            if (mPhoneDataConnectionType >= 0) {
3103                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
3104                        elapsedRealtime);
3105            }
3106            mPhoneDataConnectionType = bin;
3107            mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
3108        }
3109    }
3110
3111    public void noteWifiOnLocked() {
3112        if (!mWifiOn) {
3113            final long elapsedRealtime = SystemClock.elapsedRealtime();
3114            final long uptime = SystemClock.uptimeMillis();
3115            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
3116            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
3117                    + Integer.toHexString(mHistoryCur.states));
3118            addHistoryRecordLocked(elapsedRealtime, uptime);
3119            mWifiOn = true;
3120            mWifiOnTimer.startRunningLocked(elapsedRealtime);
3121        }
3122    }
3123
3124    public void noteWifiOffLocked() {
3125        final long elapsedRealtime = SystemClock.elapsedRealtime();
3126        final long uptime = SystemClock.uptimeMillis();
3127        if (mWifiOn) {
3128            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
3129            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
3130                    + Integer.toHexString(mHistoryCur.states));
3131            addHistoryRecordLocked(elapsedRealtime, uptime);
3132            mWifiOn = false;
3133            mWifiOnTimer.stopRunningLocked(elapsedRealtime);
3134        }
3135    }
3136
3137    public void noteAudioOnLocked(int uid) {
3138        uid = mapUid(uid);
3139        final long elapsedRealtime = SystemClock.elapsedRealtime();
3140        final long uptime = SystemClock.uptimeMillis();
3141        if (!mAudioOn) {
3142            mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
3143            if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
3144                    + Integer.toHexString(mHistoryCur.states));
3145            addHistoryRecordLocked(elapsedRealtime, uptime);
3146            mAudioOn = true;
3147            mAudioOnTimer.startRunningLocked(elapsedRealtime);
3148        }
3149        getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
3150    }
3151
3152    public void noteAudioOffLocked(int uid) {
3153        uid = mapUid(uid);
3154        final long elapsedRealtime = SystemClock.elapsedRealtime();
3155        final long uptime = SystemClock.uptimeMillis();
3156        if (mAudioOn) {
3157            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
3158            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
3159                    + Integer.toHexString(mHistoryCur.states));
3160            addHistoryRecordLocked(elapsedRealtime, uptime);
3161            mAudioOn = false;
3162            mAudioOnTimer.stopRunningLocked(elapsedRealtime);
3163        }
3164        getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
3165    }
3166
3167    public void noteVideoOnLocked(int uid) {
3168        uid = mapUid(uid);
3169        final long elapsedRealtime = SystemClock.elapsedRealtime();
3170        final long uptime = SystemClock.uptimeMillis();
3171        if (!mVideoOn) {
3172            mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
3173            if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
3174                    + Integer.toHexString(mHistoryCur.states));
3175            addHistoryRecordLocked(elapsedRealtime, uptime);
3176            mVideoOn = true;
3177            mVideoOnTimer.startRunningLocked(elapsedRealtime);
3178        }
3179        getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
3180    }
3181
3182    public void noteVideoOffLocked(int uid) {
3183        uid = mapUid(uid);
3184        final long elapsedRealtime = SystemClock.elapsedRealtime();
3185        final long uptime = SystemClock.uptimeMillis();
3186        if (mVideoOn) {
3187            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
3188            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
3189                    + Integer.toHexString(mHistoryCur.states));
3190            addHistoryRecordLocked(elapsedRealtime, uptime);
3191            mVideoOn = false;
3192            mVideoOnTimer.stopRunningLocked(elapsedRealtime);
3193        }
3194        getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
3195    }
3196
3197    public void noteActivityResumedLocked(int uid) {
3198        uid = mapUid(uid);
3199        getUidStatsLocked(uid).noteActivityResumedLocked(SystemClock.elapsedRealtime());
3200    }
3201
3202    public void noteActivityPausedLocked(int uid) {
3203        uid = mapUid(uid);
3204        getUidStatsLocked(uid).noteActivityPausedLocked(SystemClock.elapsedRealtime());
3205    }
3206
3207    public void noteVibratorOnLocked(int uid, long durationMillis) {
3208        uid = mapUid(uid);
3209        getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
3210    }
3211
3212    public void noteVibratorOffLocked(int uid) {
3213        uid = mapUid(uid);
3214        getUidStatsLocked(uid).noteVibratorOffLocked();
3215    }
3216
3217    public void noteFlashlightOnLocked() {
3218        if (!mFlashlightOn) {
3219            final long elapsedRealtime = SystemClock.elapsedRealtime();
3220            final long uptime = SystemClock.uptimeMillis();
3221            mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
3222            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
3223                    + Integer.toHexString(mHistoryCur.states));
3224            addHistoryRecordLocked(elapsedRealtime, uptime);
3225            mFlashlightOn = true;
3226            mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
3227        }
3228    }
3229
3230    public void noteFlashlightOffLocked() {
3231        final long elapsedRealtime = SystemClock.elapsedRealtime();
3232        final long uptime = SystemClock.uptimeMillis();
3233        if (mFlashlightOn) {
3234            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
3235            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
3236                    + Integer.toHexString(mHistoryCur.states));
3237            addHistoryRecordLocked(elapsedRealtime, uptime);
3238            mFlashlightOn = false;
3239            mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
3240        }
3241    }
3242
3243    public void noteWifiRunningLocked(WorkSource ws) {
3244        if (!mGlobalWifiRunning) {
3245            final long elapsedRealtime = SystemClock.elapsedRealtime();
3246            final long uptime = SystemClock.uptimeMillis();
3247            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
3248            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
3249                    + Integer.toHexString(mHistoryCur.states));
3250            addHistoryRecordLocked(elapsedRealtime, uptime);
3251            mGlobalWifiRunning = true;
3252            mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
3253            int N = ws.size();
3254            for (int i=0; i<N; i++) {
3255                int uid = mapUid(ws.get(i));
3256                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
3257            }
3258        } else {
3259            Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
3260        }
3261    }
3262
3263    public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
3264        if (mGlobalWifiRunning) {
3265            final long elapsedRealtime = SystemClock.elapsedRealtime();
3266            int N = oldWs.size();
3267            for (int i=0; i<N; i++) {
3268                int uid = mapUid(oldWs.get(i));
3269                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
3270            }
3271            N = newWs.size();
3272            for (int i=0; i<N; i++) {
3273                int uid = mapUid(newWs.get(i));
3274                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
3275            }
3276        } else {
3277            Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
3278        }
3279    }
3280
3281    public void noteWifiStoppedLocked(WorkSource ws) {
3282        if (mGlobalWifiRunning) {
3283            final long elapsedRealtime = SystemClock.elapsedRealtime();
3284            final long uptime = SystemClock.uptimeMillis();
3285            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
3286            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
3287                    + Integer.toHexString(mHistoryCur.states));
3288            addHistoryRecordLocked(elapsedRealtime, uptime);
3289            mGlobalWifiRunning = false;
3290            mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
3291            int N = ws.size();
3292            for (int i=0; i<N; i++) {
3293                int uid = mapUid(ws.get(i));
3294                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
3295            }
3296        } else {
3297            Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
3298        }
3299    }
3300
3301    public void noteWifiStateLocked(int wifiState, String accessPoint) {
3302        if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
3303        if (mWifiState != wifiState) {
3304            final long elapsedRealtime = SystemClock.elapsedRealtime();
3305            if (mWifiState >= 0) {
3306                mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
3307            }
3308            mWifiState = wifiState;
3309            mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
3310        }
3311    }
3312
3313    public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
3314        if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
3315        if (mWifiSupplState != supplState) {
3316            final long elapsedRealtime = SystemClock.elapsedRealtime();
3317            final long uptime = SystemClock.uptimeMillis();
3318            if (mWifiSupplState >= 0) {
3319                mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
3320            }
3321            mWifiSupplState = supplState;
3322            mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
3323            mHistoryCur.states2 =
3324                    (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
3325                    | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
3326            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
3327                    + Integer.toHexString(mHistoryCur.states2));
3328            addHistoryRecordLocked(elapsedRealtime, uptime);
3329        }
3330    }
3331
3332    void stopAllWifiSignalStrengthTimersLocked(int except) {
3333        final long elapsedRealtime = SystemClock.elapsedRealtime();
3334        for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
3335            if (i == except) {
3336                continue;
3337            }
3338            while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
3339                mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
3340            }
3341        }
3342    }
3343
3344    public void noteWifiRssiChangedLocked(int newRssi) {
3345        int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
3346        if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
3347        if (mWifiSignalStrengthBin != strengthBin) {
3348            final long elapsedRealtime = SystemClock.elapsedRealtime();
3349            final long uptime = SystemClock.uptimeMillis();
3350            if (mWifiSignalStrengthBin >= 0) {
3351                mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
3352                        elapsedRealtime);
3353            }
3354            if (strengthBin >= 0) {
3355                if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
3356                    mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
3357                }
3358                mHistoryCur.states2 =
3359                        (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
3360                        | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
3361                if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
3362                        + Integer.toHexString(mHistoryCur.states2));
3363                addHistoryRecordLocked(elapsedRealtime, uptime);
3364            } else {
3365                stopAllWifiSignalStrengthTimersLocked(-1);
3366            }
3367            mWifiSignalStrengthBin = strengthBin;
3368        }
3369    }
3370
3371    public void noteBluetoothOnLocked() {
3372        if (!mBluetoothOn) {
3373            final long elapsedRealtime = SystemClock.elapsedRealtime();
3374            final long uptime = SystemClock.uptimeMillis();
3375            mHistoryCur.states |= HistoryItem.STATE_BLUETOOTH_ON_FLAG;
3376            if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth on to: "
3377                    + Integer.toHexString(mHistoryCur.states));
3378            addHistoryRecordLocked(elapsedRealtime, uptime);
3379            mBluetoothOn = true;
3380            mBluetoothOnTimer.startRunningLocked(elapsedRealtime);
3381        }
3382    }
3383
3384    public void noteBluetoothOffLocked() {
3385        if (mBluetoothOn) {
3386            final long elapsedRealtime = SystemClock.elapsedRealtime();
3387            final long uptime = SystemClock.uptimeMillis();
3388            mHistoryCur.states &= ~HistoryItem.STATE_BLUETOOTH_ON_FLAG;
3389            if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth off to: "
3390                    + Integer.toHexString(mHistoryCur.states));
3391            addHistoryRecordLocked(elapsedRealtime, uptime);
3392            mBluetoothOn = false;
3393            mBluetoothOnTimer.stopRunningLocked(elapsedRealtime);
3394        }
3395    }
3396
3397    public void noteBluetoothStateLocked(int bluetoothState) {
3398        if (DEBUG) Log.i(TAG, "Bluetooth state -> " + bluetoothState);
3399        if (mBluetoothState != bluetoothState) {
3400            final long elapsedRealtime = SystemClock.elapsedRealtime();
3401            if (mBluetoothState >= 0) {
3402                mBluetoothStateTimer[mBluetoothState].stopRunningLocked(elapsedRealtime);
3403            }
3404            mBluetoothState = bluetoothState;
3405            mBluetoothStateTimer[bluetoothState].startRunningLocked(elapsedRealtime);
3406        }
3407    }
3408
3409    int mWifiFullLockNesting = 0;
3410
3411    public void noteFullWifiLockAcquiredLocked(int uid) {
3412        uid = mapUid(uid);
3413        final long elapsedRealtime = SystemClock.elapsedRealtime();
3414        final long uptime = SystemClock.uptimeMillis();
3415        if (mWifiFullLockNesting == 0) {
3416            mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
3417            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
3418                    + Integer.toHexString(mHistoryCur.states));
3419            addHistoryRecordLocked(elapsedRealtime, uptime);
3420        }
3421        mWifiFullLockNesting++;
3422        getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
3423    }
3424
3425    public void noteFullWifiLockReleasedLocked(int uid) {
3426        uid = mapUid(uid);
3427        final long elapsedRealtime = SystemClock.elapsedRealtime();
3428        final long uptime = SystemClock.uptimeMillis();
3429        mWifiFullLockNesting--;
3430        if (mWifiFullLockNesting == 0) {
3431            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
3432            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
3433                    + Integer.toHexString(mHistoryCur.states));
3434            addHistoryRecordLocked(elapsedRealtime, uptime);
3435        }
3436        getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
3437    }
3438
3439    int mWifiScanNesting = 0;
3440
3441    public void noteWifiScanStartedLocked(int uid) {
3442        uid = mapUid(uid);
3443        final long elapsedRealtime = SystemClock.elapsedRealtime();
3444        final long uptime = SystemClock.uptimeMillis();
3445        if (mWifiScanNesting == 0) {
3446            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
3447            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
3448                    + Integer.toHexString(mHistoryCur.states));
3449            addHistoryRecordLocked(elapsedRealtime, uptime);
3450        }
3451        mWifiScanNesting++;
3452        getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
3453    }
3454
3455    public void noteWifiScanStoppedLocked(int uid) {
3456        uid = mapUid(uid);
3457        final long elapsedRealtime = SystemClock.elapsedRealtime();
3458        final long uptime = SystemClock.uptimeMillis();
3459        mWifiScanNesting--;
3460        if (mWifiScanNesting == 0) {
3461            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
3462            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
3463                    + Integer.toHexString(mHistoryCur.states));
3464            addHistoryRecordLocked(elapsedRealtime, uptime);
3465        }
3466        getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
3467    }
3468
3469    public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
3470        uid = mapUid(uid);
3471        final long elapsedRealtime = SystemClock.elapsedRealtime();
3472        getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
3473    }
3474
3475    public void noteWifiBatchedScanStoppedLocked(int uid) {
3476        uid = mapUid(uid);
3477        final long elapsedRealtime = SystemClock.elapsedRealtime();
3478        getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
3479    }
3480
3481    int mWifiMulticastNesting = 0;
3482
3483    public void noteWifiMulticastEnabledLocked(int uid) {
3484        uid = mapUid(uid);
3485        final long elapsedRealtime = SystemClock.elapsedRealtime();
3486        final long uptime = SystemClock.uptimeMillis();
3487        if (mWifiMulticastNesting == 0) {
3488            mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
3489            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
3490                    + Integer.toHexString(mHistoryCur.states));
3491            addHistoryRecordLocked(elapsedRealtime, uptime);
3492        }
3493        mWifiMulticastNesting++;
3494        getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
3495    }
3496
3497    public void noteWifiMulticastDisabledLocked(int uid) {
3498        uid = mapUid(uid);
3499        final long elapsedRealtime = SystemClock.elapsedRealtime();
3500        final long uptime = SystemClock.uptimeMillis();
3501        mWifiMulticastNesting--;
3502        if (mWifiMulticastNesting == 0) {
3503            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
3504            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
3505                    + Integer.toHexString(mHistoryCur.states));
3506            addHistoryRecordLocked(elapsedRealtime, uptime);
3507        }
3508        getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
3509    }
3510
3511    public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
3512        int N = ws.size();
3513        for (int i=0; i<N; i++) {
3514            noteFullWifiLockAcquiredLocked(ws.get(i));
3515        }
3516    }
3517
3518    public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
3519        int N = ws.size();
3520        for (int i=0; i<N; i++) {
3521            noteFullWifiLockReleasedLocked(ws.get(i));
3522        }
3523    }
3524
3525    public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
3526        int N = ws.size();
3527        for (int i=0; i<N; i++) {
3528            noteWifiScanStartedLocked(ws.get(i));
3529        }
3530    }
3531
3532    public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
3533        int N = ws.size();
3534        for (int i=0; i<N; i++) {
3535            noteWifiScanStoppedLocked(ws.get(i));
3536        }
3537    }
3538
3539    public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
3540        int N = ws.size();
3541        for (int i=0; i<N; i++) {
3542            noteWifiBatchedScanStartedLocked(ws.get(i), csph);
3543        }
3544    }
3545
3546    public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
3547        int N = ws.size();
3548        for (int i=0; i<N; i++) {
3549            noteWifiBatchedScanStoppedLocked(ws.get(i));
3550        }
3551    }
3552
3553    public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
3554        int N = ws.size();
3555        for (int i=0; i<N; i++) {
3556            noteWifiMulticastEnabledLocked(ws.get(i));
3557        }
3558    }
3559
3560    public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
3561        int N = ws.size();
3562        for (int i=0; i<N; i++) {
3563            noteWifiMulticastDisabledLocked(ws.get(i));
3564        }
3565    }
3566
3567    private static String[] includeInStringArray(String[] array, String str) {
3568        if (ArrayUtils.indexOf(array, str) >= 0) {
3569            return array;
3570        }
3571        String[] newArray = new String[array.length+1];
3572        System.arraycopy(array, 0, newArray, 0, array.length);
3573        newArray[array.length] = str;
3574        return newArray;
3575    }
3576
3577    private static String[] excludeFromStringArray(String[] array, String str) {
3578        int index = ArrayUtils.indexOf(array, str);
3579        if (index >= 0) {
3580            String[] newArray = new String[array.length-1];
3581            if (index > 0) {
3582                System.arraycopy(array, 0, newArray, 0, index);
3583            }
3584            if (index < array.length-1) {
3585                System.arraycopy(array, index+1, newArray, index, array.length-index-1);
3586            }
3587            return newArray;
3588        }
3589        return array;
3590    }
3591
3592    public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
3593        if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
3594            mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
3595            if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
3596        } else {
3597            mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
3598            if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
3599        }
3600        if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
3601            mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
3602            if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
3603        } else {
3604            mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
3605            if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
3606        }
3607    }
3608
3609    public void noteNetworkStatsEnabledLocked() {
3610        // During device boot, qtaguid isn't enabled until after the inital
3611        // loading of battery stats. Now that they're enabled, take our initial
3612        // snapshot for future delta calculation.
3613        updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
3614    }
3615
3616    @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
3617        return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3618    }
3619
3620    @Override public int getScreenOnCount(int which) {
3621        return mScreenOnTimer.getCountLocked(which);
3622    }
3623
3624    @Override public long getScreenBrightnessTime(int brightnessBin,
3625            long elapsedRealtimeUs, int which) {
3626        return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
3627                elapsedRealtimeUs, which);
3628    }
3629
3630    @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
3631        return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3632    }
3633
3634    @Override public long getLowPowerModeEnabledTime(long elapsedRealtimeUs, int which) {
3635        return mLowPowerModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3636    }
3637
3638    @Override public int getLowPowerModeEnabledCount(int which) {
3639        return mLowPowerModeEnabledTimer.getCountLocked(which);
3640    }
3641
3642    @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
3643        return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3644    }
3645
3646    @Override public int getPhoneOnCount(int which) {
3647        return mPhoneOnTimer.getCountLocked(which);
3648    }
3649
3650    @Override public long getPhoneSignalStrengthTime(int strengthBin,
3651            long elapsedRealtimeUs, int which) {
3652        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
3653                elapsedRealtimeUs, which);
3654    }
3655
3656    @Override public long getPhoneSignalScanningTime(
3657            long elapsedRealtimeUs, int which) {
3658        return mPhoneSignalScanningTimer.getTotalTimeLocked(
3659                elapsedRealtimeUs, which);
3660    }
3661
3662    @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
3663        return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
3664    }
3665
3666    @Override public long getPhoneDataConnectionTime(int dataType,
3667            long elapsedRealtimeUs, int which) {
3668        return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
3669                elapsedRealtimeUs, which);
3670    }
3671
3672    @Override public int getPhoneDataConnectionCount(int dataType, int which) {
3673        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
3674    }
3675
3676    @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
3677        return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3678    }
3679
3680    @Override public int getMobileRadioActiveCount(int which) {
3681        return mMobileRadioActiveTimer.getCountLocked(which);
3682    }
3683
3684    @Override public long getMobileRadioActiveAdjustedTime(int which) {
3685        return mMobileRadioActiveAdjustedTime.getCountLocked(which);
3686    }
3687
3688    @Override public long getMobileRadioActiveUnknownTime(int which) {
3689        return mMobileRadioActiveUnknownTime.getCountLocked(which);
3690    }
3691
3692    @Override public int getMobileRadioActiveUnknownCount(int which) {
3693        return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
3694    }
3695
3696    @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
3697        return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3698    }
3699
3700    @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
3701        return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3702    }
3703
3704    @Override public long getWifiStateTime(int wifiState,
3705            long elapsedRealtimeUs, int which) {
3706        return mWifiStateTimer[wifiState].getTotalTimeLocked(
3707                elapsedRealtimeUs, which);
3708    }
3709
3710    @Override public int getWifiStateCount(int wifiState, int which) {
3711        return mWifiStateTimer[wifiState].getCountLocked(which);
3712    }
3713
3714    @Override public long getWifiSupplStateTime(int state,
3715            long elapsedRealtimeUs, int which) {
3716        return mWifiSupplStateTimer[state].getTotalTimeLocked(
3717                elapsedRealtimeUs, which);
3718    }
3719
3720    @Override public int getWifiSupplStateCount(int state, int which) {
3721        return mWifiSupplStateTimer[state].getCountLocked(which);
3722    }
3723
3724    @Override public long getWifiSignalStrengthTime(int strengthBin,
3725            long elapsedRealtimeUs, int which) {
3726        return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
3727                elapsedRealtimeUs, which);
3728    }
3729
3730    @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
3731        return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
3732    }
3733
3734    @Override public long getBluetoothOnTime(long elapsedRealtimeUs, int which) {
3735        return mBluetoothOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3736    }
3737
3738    @Override public long getBluetoothStateTime(int bluetoothState,
3739            long elapsedRealtimeUs, int which) {
3740        return mBluetoothStateTimer[bluetoothState].getTotalTimeLocked(
3741                elapsedRealtimeUs, which);
3742    }
3743
3744    @Override public int getBluetoothStateCount(int bluetoothState, int which) {
3745        return mBluetoothStateTimer[bluetoothState].getCountLocked(which);
3746    }
3747
3748    @Override public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
3749        return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
3750    }
3751
3752    @Override public long getFlashlightOnCount(int which) {
3753        return mFlashlightOnTimer.getCountLocked(which);
3754    }
3755
3756    @Override
3757    public long getNetworkActivityBytes(int type, int which) {
3758        if (type >= 0 && type < mNetworkByteActivityCounters.length) {
3759            return mNetworkByteActivityCounters[type].getCountLocked(which);
3760        } else {
3761            return 0;
3762        }
3763    }
3764
3765    @Override
3766    public long getNetworkActivityPackets(int type, int which) {
3767        if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
3768            return mNetworkPacketActivityCounters[type].getCountLocked(which);
3769        } else {
3770            return 0;
3771        }
3772    }
3773
3774    @Override public long getStartClockTime() {
3775        return mStartClockTime;
3776    }
3777
3778    @Override public boolean getIsOnBattery() {
3779        return mOnBattery;
3780    }
3781
3782    @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
3783        return mUidStats;
3784    }
3785
3786    /**
3787     * The statistics associated with a particular uid.
3788     */
3789    public final class Uid extends BatteryStats.Uid {
3790
3791        final int mUid;
3792
3793        boolean mWifiRunning;
3794        StopwatchTimer mWifiRunningTimer;
3795
3796        boolean mFullWifiLockOut;
3797        StopwatchTimer mFullWifiLockTimer;
3798
3799        boolean mWifiScanStarted;
3800        StopwatchTimer mWifiScanTimer;
3801
3802        static final int NO_BATCHED_SCAN_STARTED = -1;
3803        int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
3804        StopwatchTimer[] mWifiBatchedScanTimer;
3805
3806        boolean mWifiMulticastEnabled;
3807        StopwatchTimer mWifiMulticastTimer;
3808
3809        boolean mAudioTurnedOn;
3810        StopwatchTimer mAudioTurnedOnTimer;
3811
3812        boolean mVideoTurnedOn;
3813        StopwatchTimer mVideoTurnedOnTimer;
3814
3815        StopwatchTimer mForegroundActivityTimer;
3816
3817        static final int PROCESS_STATE_NONE = NUM_PROCESS_STATE;
3818        int mProcessState = PROCESS_STATE_NONE;
3819        StopwatchTimer[] mProcessStateTimer;
3820
3821        BatchTimer mVibratorOnTimer;
3822
3823        Counter[] mUserActivityCounters;
3824
3825        LongSamplingCounter[] mNetworkByteActivityCounters;
3826        LongSamplingCounter[] mNetworkPacketActivityCounters;
3827        LongSamplingCounter mMobileRadioActiveTime;
3828        LongSamplingCounter mMobileRadioActiveCount;
3829
3830        /**
3831         * The statistics we have collected for this uid's wake locks.
3832         */
3833        final ArrayMap<String, Wakelock> mWakelockStats = new ArrayMap<String, Wakelock>();
3834
3835        /**
3836         * The statistics we have collected for this uid's sensor activations.
3837         */
3838        final SparseArray<Sensor> mSensorStats = new SparseArray<Sensor>();
3839
3840        /**
3841         * The statistics we have collected for this uid's processes.
3842         */
3843        final ArrayMap<String, Proc> mProcessStats = new ArrayMap<String, Proc>();
3844
3845        /**
3846         * The statistics we have collected for this uid's processes.
3847         */
3848        final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<String, Pkg>();
3849
3850        /**
3851         * The transient wake stats we have collected for this uid's pids.
3852         */
3853        final SparseArray<Pid> mPids = new SparseArray<Pid>();
3854
3855        public Uid(int uid) {
3856            mUid = uid;
3857            mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
3858                    mWifiRunningTimers, mOnBatteryTimeBase);
3859            mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
3860                    mFullWifiLockTimers, mOnBatteryTimeBase);
3861            mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
3862                    mWifiScanTimers, mOnBatteryTimeBase);
3863            mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
3864            mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
3865                    mWifiMulticastTimers, mOnBatteryTimeBase);
3866            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
3867        }
3868
3869        @Override
3870        public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
3871            return mWakelockStats;
3872        }
3873
3874        @Override
3875        public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
3876            return mSensorStats;
3877        }
3878
3879        @Override
3880        public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
3881            return mProcessStats;
3882        }
3883
3884        @Override
3885        public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
3886            return mPackageStats;
3887        }
3888
3889        @Override
3890        public int getUid() {
3891            return mUid;
3892        }
3893
3894        @Override
3895        public void noteWifiRunningLocked(long elapsedRealtimeMs) {
3896            if (!mWifiRunning) {
3897                mWifiRunning = true;
3898                if (mWifiRunningTimer == null) {
3899                    mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
3900                            mWifiRunningTimers, mOnBatteryTimeBase);
3901                }
3902                mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
3903            }
3904        }
3905
3906        @Override
3907        public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
3908            if (mWifiRunning) {
3909                mWifiRunning = false;
3910                mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
3911            }
3912        }
3913
3914        @Override
3915        public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
3916            if (!mFullWifiLockOut) {
3917                mFullWifiLockOut = true;
3918                if (mFullWifiLockTimer == null) {
3919                    mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
3920                            mFullWifiLockTimers, mOnBatteryTimeBase);
3921                }
3922                mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
3923            }
3924        }
3925
3926        @Override
3927        public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
3928            if (mFullWifiLockOut) {
3929                mFullWifiLockOut = false;
3930                mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
3931            }
3932        }
3933
3934        @Override
3935        public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
3936            if (!mWifiScanStarted) {
3937                mWifiScanStarted = true;
3938                if (mWifiScanTimer == null) {
3939                    mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
3940                            mWifiScanTimers, mOnBatteryTimeBase);
3941                }
3942                mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
3943            }
3944        }
3945
3946        @Override
3947        public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
3948            if (mWifiScanStarted) {
3949                mWifiScanStarted = false;
3950                mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
3951            }
3952        }
3953
3954        @Override
3955        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
3956            int bin = 0;
3957            while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) {
3958                csph = csph >> 3;
3959                bin++;
3960            }
3961
3962            if (mWifiBatchedScanBinStarted == bin) return;
3963
3964            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
3965                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
3966                        stopRunningLocked(elapsedRealtimeMs);
3967            }
3968            mWifiBatchedScanBinStarted = bin;
3969            if (mWifiBatchedScanTimer[bin] == null) {
3970                makeWifiBatchedScanBin(bin, null);
3971            }
3972            mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
3973        }
3974
3975        @Override
3976        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
3977            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
3978                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
3979                        stopRunningLocked(elapsedRealtimeMs);
3980                mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
3981            }
3982        }
3983
3984        @Override
3985        public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
3986            if (!mWifiMulticastEnabled) {
3987                mWifiMulticastEnabled = true;
3988                if (mWifiMulticastTimer == null) {
3989                    mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
3990                            mWifiMulticastTimers, mOnBatteryTimeBase);
3991                }
3992                mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
3993            }
3994        }
3995
3996        @Override
3997        public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
3998            if (mWifiMulticastEnabled) {
3999                mWifiMulticastEnabled = false;
4000                mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
4001            }
4002        }
4003
4004        public StopwatchTimer createAudioTurnedOnTimerLocked() {
4005            if (mAudioTurnedOnTimer == null) {
4006                mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
4007                        null, mOnBatteryTimeBase);
4008            }
4009            return mAudioTurnedOnTimer;
4010        }
4011
4012        @Override
4013        public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
4014            if (!mAudioTurnedOn) {
4015                mAudioTurnedOn = true;
4016                createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4017            }
4018        }
4019
4020        @Override
4021        public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
4022            if (mAudioTurnedOn) {
4023                mAudioTurnedOn = false;
4024                if (mAudioTurnedOnTimer != null) {
4025                    mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4026                }
4027            }
4028        }
4029
4030        public StopwatchTimer createVideoTurnedOnTimerLocked() {
4031            if (mVideoTurnedOnTimer == null) {
4032                mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
4033                        null, mOnBatteryTimeBase);
4034            }
4035            return mVideoTurnedOnTimer;
4036        }
4037
4038        @Override
4039        public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
4040            if (!mVideoTurnedOn) {
4041                mVideoTurnedOn = true;
4042                createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4043            }
4044        }
4045
4046        @Override
4047        public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
4048            if (mVideoTurnedOn) {
4049                mVideoTurnedOn = false;
4050                if (mVideoTurnedOnTimer != null) {
4051                    mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4052                }
4053            }
4054        }
4055
4056        public StopwatchTimer createForegroundActivityTimerLocked() {
4057            if (mForegroundActivityTimer == null) {
4058                mForegroundActivityTimer = new StopwatchTimer(
4059                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase);
4060            }
4061            return mForegroundActivityTimer;
4062        }
4063
4064        @Override
4065        public void noteActivityResumedLocked(long elapsedRealtimeMs) {
4066            // We always start, since we want multiple foreground PIDs to nest
4067            createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
4068        }
4069
4070        @Override
4071        public void noteActivityPausedLocked(long elapsedRealtimeMs) {
4072            if (mForegroundActivityTimer != null) {
4073                mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
4074            }
4075        }
4076
4077        void updateUidProcessStateLocked(int state, long elapsedRealtimeMs) {
4078            if (mProcessState == state) return;
4079
4080            if (mProcessState != PROCESS_STATE_NONE) {
4081                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
4082            }
4083            mProcessState = state;
4084            if (state != PROCESS_STATE_NONE) {
4085                if (mProcessStateTimer[state] == null) {
4086                    makeProcessState(state, null);
4087                }
4088                mProcessStateTimer[state].startRunningLocked(elapsedRealtimeMs);
4089            }
4090        }
4091
4092        public BatchTimer createVibratorOnTimerLocked() {
4093            if (mVibratorOnTimer == null) {
4094                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
4095            }
4096            return mVibratorOnTimer;
4097        }
4098
4099        public void noteVibratorOnLocked(long durationMillis) {
4100            createVibratorOnTimerLocked().addDuration(BatteryStatsImpl.this, durationMillis);
4101        }
4102
4103        public void noteVibratorOffLocked() {
4104            if (mVibratorOnTimer != null) {
4105                mVibratorOnTimer.abortLastDuration(BatteryStatsImpl.this);
4106            }
4107        }
4108
4109        @Override
4110        public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
4111            if (mWifiRunningTimer == null) {
4112                return 0;
4113            }
4114            return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4115        }
4116
4117        @Override
4118        public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
4119            if (mFullWifiLockTimer == null) {
4120                return 0;
4121            }
4122            return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4123        }
4124
4125        @Override
4126        public long getWifiScanTime(long elapsedRealtimeUs, int which) {
4127            if (mWifiScanTimer == null) {
4128                return 0;
4129            }
4130            return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4131        }
4132
4133        @Override
4134        public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
4135            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
4136            if (mWifiBatchedScanTimer[csphBin] == null) {
4137                return 0;
4138            }
4139            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
4140        }
4141
4142        @Override
4143        public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
4144            if (mWifiMulticastTimer == null) {
4145                return 0;
4146            }
4147            return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4148        }
4149
4150        @Override
4151        public long getAudioTurnedOnTime(long elapsedRealtimeUs, int which) {
4152            if (mAudioTurnedOnTimer == null) {
4153                return 0;
4154            }
4155            return mAudioTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4156        }
4157
4158        @Override
4159        public long getVideoTurnedOnTime(long elapsedRealtimeUs, int which) {
4160            if (mVideoTurnedOnTimer == null) {
4161                return 0;
4162            }
4163            return mVideoTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4164        }
4165
4166        @Override
4167        public Timer getForegroundActivityTimer() {
4168            return mForegroundActivityTimer;
4169        }
4170
4171        void makeProcessState(int i, Parcel in) {
4172            if (i < 0 || i >= NUM_PROCESS_STATE) return;
4173
4174            if (in == null) {
4175                mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
4176                        mOnBatteryTimeBase);
4177            } else {
4178                mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
4179                        mOnBatteryTimeBase, in);
4180            }
4181        }
4182
4183        @Override
4184        public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
4185            if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
4186            if (mProcessStateTimer[state] == null) {
4187                return 0;
4188            }
4189            return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
4190        }
4191
4192        @Override
4193        public Timer getVibratorOnTimer() {
4194            return mVibratorOnTimer;
4195        }
4196
4197        @Override
4198        public void noteUserActivityLocked(int type) {
4199            if (mUserActivityCounters == null) {
4200                initUserActivityLocked();
4201            }
4202            if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
4203                mUserActivityCounters[type].stepAtomic();
4204            } else {
4205                Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
4206                        new Throwable());
4207            }
4208        }
4209
4210        @Override
4211        public boolean hasUserActivity() {
4212            return mUserActivityCounters != null;
4213        }
4214
4215        @Override
4216        public int getUserActivityCount(int type, int which) {
4217            if (mUserActivityCounters == null) {
4218                return 0;
4219            }
4220            return mUserActivityCounters[type].getCountLocked(which);
4221        }
4222
4223        void makeWifiBatchedScanBin(int i, Parcel in) {
4224            if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
4225
4226            ArrayList<StopwatchTimer> collected = mWifiBatchedScanTimers.get(i);
4227            if (collected == null) {
4228                collected = new ArrayList<StopwatchTimer>();
4229                mWifiBatchedScanTimers.put(i, collected);
4230            }
4231            if (in == null) {
4232                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
4233                        mOnBatteryTimeBase);
4234            } else {
4235                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
4236                        mOnBatteryTimeBase, in);
4237            }
4238        }
4239
4240
4241        void initUserActivityLocked() {
4242            mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
4243            for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
4244                mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase);
4245            }
4246        }
4247
4248        void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
4249            if (mNetworkByteActivityCounters == null) {
4250                initNetworkActivityLocked();
4251            }
4252            if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
4253                mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
4254                mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
4255            } else {
4256                Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
4257                        new Throwable());
4258            }
4259        }
4260
4261        void noteMobileRadioActiveTimeLocked(long batteryUptime) {
4262            if (mNetworkByteActivityCounters == null) {
4263                initNetworkActivityLocked();
4264            }
4265            mMobileRadioActiveTime.addCountLocked(batteryUptime);
4266            mMobileRadioActiveCount.addCountLocked(1);
4267        }
4268
4269        @Override
4270        public boolean hasNetworkActivity() {
4271            return mNetworkByteActivityCounters != null;
4272        }
4273
4274        @Override
4275        public long getNetworkActivityBytes(int type, int which) {
4276            if (mNetworkByteActivityCounters != null && type >= 0
4277                    && type < mNetworkByteActivityCounters.length) {
4278                return mNetworkByteActivityCounters[type].getCountLocked(which);
4279            } else {
4280                return 0;
4281            }
4282        }
4283
4284        @Override
4285        public long getNetworkActivityPackets(int type, int which) {
4286            if (mNetworkPacketActivityCounters != null && type >= 0
4287                    && type < mNetworkPacketActivityCounters.length) {
4288                return mNetworkPacketActivityCounters[type].getCountLocked(which);
4289            } else {
4290                return 0;
4291            }
4292        }
4293
4294        @Override
4295        public long getMobileRadioActiveTime(int which) {
4296            return mMobileRadioActiveTime != null
4297                    ? mMobileRadioActiveTime.getCountLocked(which) : 0;
4298        }
4299
4300        @Override
4301        public int getMobileRadioActiveCount(int which) {
4302            return mMobileRadioActiveCount != null
4303                    ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
4304        }
4305
4306        void initNetworkActivityLocked() {
4307            mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
4308            mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
4309            for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
4310                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
4311                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
4312            }
4313            mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase);
4314            mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase);
4315        }
4316
4317        /**
4318         * Clear all stats for this uid.  Returns true if the uid is completely
4319         * inactive so can be dropped.
4320         */
4321        boolean reset() {
4322            boolean active = false;
4323
4324            if (mWifiRunningTimer != null) {
4325                active |= !mWifiRunningTimer.reset(false);
4326                active |= mWifiRunning;
4327            }
4328            if (mFullWifiLockTimer != null) {
4329                active |= !mFullWifiLockTimer.reset(false);
4330                active |= mFullWifiLockOut;
4331            }
4332            if (mWifiScanTimer != null) {
4333                active |= !mWifiScanTimer.reset(false);
4334                active |= mWifiScanStarted;
4335            }
4336            if (mWifiBatchedScanTimer != null) {
4337                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
4338                    if (mWifiBatchedScanTimer[i] != null) {
4339                        active |= !mWifiBatchedScanTimer[i].reset(false);
4340                    }
4341                }
4342                active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
4343            }
4344            if (mWifiMulticastTimer != null) {
4345                active |= !mWifiMulticastTimer.reset(false);
4346                active |= mWifiMulticastEnabled;
4347            }
4348            if (mAudioTurnedOnTimer != null) {
4349                active |= !mAudioTurnedOnTimer.reset(false);
4350                active |= mAudioTurnedOn;
4351            }
4352            if (mVideoTurnedOnTimer != null) {
4353                active |= !mVideoTurnedOnTimer.reset(false);
4354                active |= mVideoTurnedOn;
4355            }
4356            if (mForegroundActivityTimer != null) {
4357                active |= !mForegroundActivityTimer.reset(false);
4358            }
4359            if (mProcessStateTimer != null) {
4360                for (int i = 0; i < NUM_PROCESS_STATE; i++) {
4361                    if (mProcessStateTimer[i] != null) {
4362                        active |= !mProcessStateTimer[i].reset(false);
4363                    }
4364                }
4365                active |= (mProcessState != PROCESS_STATE_NONE);
4366            }
4367            if (mVibratorOnTimer != null) {
4368                if (mVibratorOnTimer.reset(false)) {
4369                    mVibratorOnTimer.detach();
4370                    mVibratorOnTimer = null;
4371                } else {
4372                    active = true;
4373                }
4374            }
4375
4376            if (mUserActivityCounters != null) {
4377                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
4378                    mUserActivityCounters[i].reset(false);
4379                }
4380            }
4381
4382            if (mNetworkByteActivityCounters != null) {
4383                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
4384                    mNetworkByteActivityCounters[i].reset(false);
4385                    mNetworkPacketActivityCounters[i].reset(false);
4386                }
4387                mMobileRadioActiveTime.reset(false);
4388                mMobileRadioActiveCount.reset(false);
4389            }
4390
4391            for (int iw=mWakelockStats.size()-1; iw>=0; iw--) {
4392                Wakelock wl = mWakelockStats.valueAt(iw);
4393                if (wl.reset()) {
4394                    mWakelockStats.removeAt(iw);
4395                } else {
4396                    active = true;
4397                }
4398            }
4399            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
4400                Sensor s = mSensorStats.valueAt(ise);
4401                if (s.reset()) {
4402                    mSensorStats.removeAt(ise);
4403                } else {
4404                    active = true;
4405                }
4406            }
4407            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
4408                Proc proc = mProcessStats.valueAt(ip);
4409                if (proc.mProcessState == PROCESS_STATE_NONE) {
4410                    proc.detach();
4411                    mProcessStats.removeAt(ip);
4412                } else {
4413                    active = true;
4414                }
4415            }
4416            if (mPids.size() > 0) {
4417                for (int i=mPids.size()-1; i>=0; i--) {
4418                    Pid pid = mPids.valueAt(i);
4419                    if (pid.mWakeNesting > 0) {
4420                        active = true;
4421                    } else {
4422                        mPids.removeAt(i);
4423                    }
4424                }
4425            }
4426            if (mPackageStats.size() > 0) {
4427                Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
4428                while (it.hasNext()) {
4429                    Map.Entry<String, Pkg> pkgEntry = it.next();
4430                    Pkg p = pkgEntry.getValue();
4431                    p.detach();
4432                    if (p.mServiceStats.size() > 0) {
4433                        Iterator<Map.Entry<String, Pkg.Serv>> it2
4434                                = p.mServiceStats.entrySet().iterator();
4435                        while (it2.hasNext()) {
4436                            Map.Entry<String, Pkg.Serv> servEntry = it2.next();
4437                            servEntry.getValue().detach();
4438                        }
4439                    }
4440                }
4441                mPackageStats.clear();
4442            }
4443
4444            if (!active) {
4445                if (mWifiRunningTimer != null) {
4446                    mWifiRunningTimer.detach();
4447                }
4448                if (mFullWifiLockTimer != null) {
4449                    mFullWifiLockTimer.detach();
4450                }
4451                if (mWifiScanTimer != null) {
4452                    mWifiScanTimer.detach();
4453                }
4454                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
4455                    if (mWifiBatchedScanTimer[i] != null) {
4456                        mWifiBatchedScanTimer[i].detach();
4457                    }
4458                }
4459                if (mWifiMulticastTimer != null) {
4460                    mWifiMulticastTimer.detach();
4461                }
4462                if (mAudioTurnedOnTimer != null) {
4463                    mAudioTurnedOnTimer.detach();
4464                    mAudioTurnedOnTimer = null;
4465                }
4466                if (mVideoTurnedOnTimer != null) {
4467                    mVideoTurnedOnTimer.detach();
4468                    mVideoTurnedOnTimer = null;
4469                }
4470                if (mForegroundActivityTimer != null) {
4471                    mForegroundActivityTimer.detach();
4472                    mForegroundActivityTimer = null;
4473                }
4474                if (mUserActivityCounters != null) {
4475                    for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
4476                        mUserActivityCounters[i].detach();
4477                    }
4478                }
4479                if (mNetworkByteActivityCounters != null) {
4480                    for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
4481                        mNetworkByteActivityCounters[i].detach();
4482                        mNetworkPacketActivityCounters[i].detach();
4483                    }
4484                }
4485                mPids.clear();
4486            }
4487
4488            return !active;
4489        }
4490
4491        void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
4492            int NW = mWakelockStats.size();
4493            out.writeInt(NW);
4494            for (int iw=0; iw<NW; iw++) {
4495                out.writeString(mWakelockStats.keyAt(iw));
4496                Uid.Wakelock wakelock = mWakelockStats.valueAt(iw);
4497                wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
4498            }
4499
4500            int NSE = mSensorStats.size();
4501            out.writeInt(NSE);
4502            for (int ise=0; ise<NSE; ise++) {
4503                out.writeInt(mSensorStats.keyAt(ise));
4504                Uid.Sensor sensor = mSensorStats.valueAt(ise);
4505                sensor.writeToParcelLocked(out, elapsedRealtimeUs);
4506            }
4507
4508            int NP = mProcessStats.size();
4509            out.writeInt(NP);
4510            for (int ip=0; ip<NP; ip++) {
4511                out.writeString(mProcessStats.keyAt(ip));
4512                Uid.Proc proc = mProcessStats.valueAt(ip);
4513                proc.writeToParcelLocked(out);
4514            }
4515
4516            out.writeInt(mPackageStats.size());
4517            for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
4518                out.writeString(pkgEntry.getKey());
4519                Uid.Pkg pkg = pkgEntry.getValue();
4520                pkg.writeToParcelLocked(out);
4521            }
4522
4523            if (mWifiRunningTimer != null) {
4524                out.writeInt(1);
4525                mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
4526            } else {
4527                out.writeInt(0);
4528            }
4529            if (mFullWifiLockTimer != null) {
4530                out.writeInt(1);
4531                mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
4532            } else {
4533                out.writeInt(0);
4534            }
4535            if (mWifiScanTimer != null) {
4536                out.writeInt(1);
4537                mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
4538            } else {
4539                out.writeInt(0);
4540            }
4541            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
4542                if (mWifiBatchedScanTimer[i] != null) {
4543                    out.writeInt(1);
4544                    mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
4545                } else {
4546                    out.writeInt(0);
4547                }
4548            }
4549            if (mWifiMulticastTimer != null) {
4550                out.writeInt(1);
4551                mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
4552            } else {
4553                out.writeInt(0);
4554            }
4555            if (mAudioTurnedOnTimer != null) {
4556                out.writeInt(1);
4557                mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
4558            } else {
4559                out.writeInt(0);
4560            }
4561            if (mVideoTurnedOnTimer != null) {
4562                out.writeInt(1);
4563                mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
4564            } else {
4565                out.writeInt(0);
4566            }
4567            if (mForegroundActivityTimer != null) {
4568                out.writeInt(1);
4569                mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
4570            } else {
4571                out.writeInt(0);
4572            }
4573            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
4574                if (mProcessStateTimer[i] != null) {
4575                    out.writeInt(1);
4576                    mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
4577                } else {
4578                    out.writeInt(0);
4579                }
4580            }
4581            if (mVibratorOnTimer != null) {
4582                out.writeInt(1);
4583                mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
4584            } else {
4585                out.writeInt(0);
4586            }
4587            if (mUserActivityCounters != null) {
4588                out.writeInt(1);
4589                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
4590                    mUserActivityCounters[i].writeToParcel(out);
4591                }
4592            } else {
4593                out.writeInt(0);
4594            }
4595            if (mNetworkByteActivityCounters != null) {
4596                out.writeInt(1);
4597                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
4598                    mNetworkByteActivityCounters[i].writeToParcel(out);
4599                    mNetworkPacketActivityCounters[i].writeToParcel(out);
4600                }
4601                mMobileRadioActiveTime.writeToParcel(out);
4602                mMobileRadioActiveCount.writeToParcel(out);
4603            } else {
4604                out.writeInt(0);
4605            }
4606        }
4607
4608        void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
4609            int numWakelocks = in.readInt();
4610            mWakelockStats.clear();
4611            for (int j = 0; j < numWakelocks; j++) {
4612                String wakelockName = in.readString();
4613                Uid.Wakelock wakelock = new Wakelock();
4614                wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
4615                // We will just drop some random set of wakelocks if
4616                // the previous run of the system was an older version
4617                // that didn't impose a limit.
4618                mWakelockStats.put(wakelockName, wakelock);
4619            }
4620
4621            int numSensors = in.readInt();
4622            mSensorStats.clear();
4623            for (int k = 0; k < numSensors; k++) {
4624                int sensorNumber = in.readInt();
4625                Uid.Sensor sensor = new Sensor(sensorNumber);
4626                sensor.readFromParcelLocked(mOnBatteryTimeBase, in);
4627                mSensorStats.put(sensorNumber, sensor);
4628            }
4629
4630            int numProcs = in.readInt();
4631            mProcessStats.clear();
4632            for (int k = 0; k < numProcs; k++) {
4633                String processName = in.readString();
4634                Uid.Proc proc = new Proc();
4635                proc.readFromParcelLocked(in);
4636                mProcessStats.put(processName, proc);
4637            }
4638
4639            int numPkgs = in.readInt();
4640            mPackageStats.clear();
4641            for (int l = 0; l < numPkgs; l++) {
4642                String packageName = in.readString();
4643                Uid.Pkg pkg = new Pkg();
4644                pkg.readFromParcelLocked(in);
4645                mPackageStats.put(packageName, pkg);
4646            }
4647
4648            mWifiRunning = false;
4649            if (in.readInt() != 0) {
4650                mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
4651                        mWifiRunningTimers, mOnBatteryTimeBase, in);
4652            } else {
4653                mWifiRunningTimer = null;
4654            }
4655            mFullWifiLockOut = false;
4656            if (in.readInt() != 0) {
4657                mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
4658                        mFullWifiLockTimers, mOnBatteryTimeBase, in);
4659            } else {
4660                mFullWifiLockTimer = null;
4661            }
4662            mWifiScanStarted = false;
4663            if (in.readInt() != 0) {
4664                mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
4665                        mWifiScanTimers, mOnBatteryTimeBase, in);
4666            } else {
4667                mWifiScanTimer = null;
4668            }
4669            mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
4670            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
4671                if (in.readInt() != 0) {
4672                    makeWifiBatchedScanBin(i, in);
4673                } else {
4674                    mWifiBatchedScanTimer[i] = null;
4675                }
4676            }
4677            mWifiMulticastEnabled = false;
4678            if (in.readInt() != 0) {
4679                mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
4680                        mWifiMulticastTimers, mOnBatteryTimeBase, in);
4681            } else {
4682                mWifiMulticastTimer = null;
4683            }
4684            mAudioTurnedOn = false;
4685            if (in.readInt() != 0) {
4686                mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
4687                        null, mOnBatteryTimeBase, in);
4688            } else {
4689                mAudioTurnedOnTimer = null;
4690            }
4691            mVideoTurnedOn = false;
4692            if (in.readInt() != 0) {
4693                mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
4694                        null, mOnBatteryTimeBase, in);
4695            } else {
4696                mVideoTurnedOnTimer = null;
4697            }
4698            if (in.readInt() != 0) {
4699                mForegroundActivityTimer = new StopwatchTimer(
4700                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase, in);
4701            } else {
4702                mForegroundActivityTimer = null;
4703            }
4704            mProcessState = PROCESS_STATE_NONE;
4705            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
4706                if (in.readInt() != 0) {
4707                    makeProcessState(i, in);
4708                } else {
4709                    mProcessStateTimer[i] = null;
4710                }
4711            }
4712            if (in.readInt() != 0) {
4713                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase, in);
4714            } else {
4715                mVibratorOnTimer = null;
4716            }
4717            if (in.readInt() != 0) {
4718                mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
4719                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
4720                    mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase, in);
4721                }
4722            } else {
4723                mUserActivityCounters = null;
4724            }
4725            if (in.readInt() != 0) {
4726                mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
4727                mNetworkPacketActivityCounters
4728                        = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
4729                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
4730                    mNetworkByteActivityCounters[i]
4731                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
4732                    mNetworkPacketActivityCounters[i]
4733                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
4734                }
4735                mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
4736                mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
4737            } else {
4738                mNetworkByteActivityCounters = null;
4739                mNetworkPacketActivityCounters = null;
4740            }
4741        }
4742
4743        /**
4744         * The statistics associated with a particular wake lock.
4745         */
4746        public final class Wakelock extends BatteryStats.Uid.Wakelock {
4747            /**
4748             * How long (in ms) this uid has been keeping the device partially awake.
4749             */
4750            StopwatchTimer mTimerPartial;
4751
4752            /**
4753             * How long (in ms) this uid has been keeping the device fully awake.
4754             */
4755            StopwatchTimer mTimerFull;
4756
4757            /**
4758             * How long (in ms) this uid has had a window keeping the device awake.
4759             */
4760            StopwatchTimer mTimerWindow;
4761
4762            /**
4763             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
4764             * proper timer pool from the given BatteryStatsImpl object.
4765             *
4766             * @param in the Parcel to be read from.
4767             * return a new Timer, or null.
4768             */
4769            private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
4770                    TimeBase timeBase, Parcel in) {
4771                if (in.readInt() == 0) {
4772                    return null;
4773                }
4774
4775                return new StopwatchTimer(Uid.this, type, pool, timeBase, in);
4776            }
4777
4778            boolean reset() {
4779                boolean wlactive = false;
4780                if (mTimerFull != null) {
4781                    wlactive |= !mTimerFull.reset(false);
4782                }
4783                if (mTimerPartial != null) {
4784                    wlactive |= !mTimerPartial.reset(false);
4785                }
4786                if (mTimerWindow != null) {
4787                    wlactive |= !mTimerWindow.reset(false);
4788                }
4789                if (!wlactive) {
4790                    if (mTimerFull != null) {
4791                        mTimerFull.detach();
4792                        mTimerFull = null;
4793                    }
4794                    if (mTimerPartial != null) {
4795                        mTimerPartial.detach();
4796                        mTimerPartial = null;
4797                    }
4798                    if (mTimerWindow != null) {
4799                        mTimerWindow.detach();
4800                        mTimerWindow = null;
4801                    }
4802                }
4803                return !wlactive;
4804            }
4805
4806            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
4807                mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
4808                        mPartialTimers, screenOffTimeBase, in);
4809                mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
4810                        mFullTimers, timeBase, in);
4811                mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
4812                        mWindowTimers, timeBase, in);
4813            }
4814
4815            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
4816                Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
4817                Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
4818                Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
4819            }
4820
4821            @Override
4822            public Timer getWakeTime(int type) {
4823                switch (type) {
4824                case WAKE_TYPE_FULL: return mTimerFull;
4825                case WAKE_TYPE_PARTIAL: return mTimerPartial;
4826                case WAKE_TYPE_WINDOW: return mTimerWindow;
4827                default: throw new IllegalArgumentException("type = " + type);
4828                }
4829            }
4830        }
4831
4832        public final class Sensor extends BatteryStats.Uid.Sensor {
4833            final int mHandle;
4834            StopwatchTimer mTimer;
4835
4836            public Sensor(int handle) {
4837                mHandle = handle;
4838            }
4839
4840            private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) {
4841                if (in.readInt() == 0) {
4842                    return null;
4843                }
4844
4845                ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
4846                if (pool == null) {
4847                    pool = new ArrayList<StopwatchTimer>();
4848                    mSensorTimers.put(mHandle, pool);
4849                }
4850                return new StopwatchTimer(Uid.this, 0, pool, timeBase, in);
4851            }
4852
4853            boolean reset() {
4854                if (mTimer.reset(true)) {
4855                    mTimer = null;
4856                    return true;
4857                }
4858                return false;
4859            }
4860
4861            void readFromParcelLocked(TimeBase timeBase, Parcel in) {
4862                mTimer = readTimerFromParcel(timeBase, in);
4863            }
4864
4865            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
4866                Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
4867            }
4868
4869            @Override
4870            public Timer getSensorTime() {
4871                return mTimer;
4872            }
4873
4874            @Override
4875            public int getHandle() {
4876                return mHandle;
4877            }
4878        }
4879
4880        /**
4881         * The statistics associated with a particular process.
4882         */
4883        public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
4884            /**
4885             * Remains true until removed from the stats.
4886             */
4887            boolean mActive = true;
4888
4889            /**
4890             * Total time (in 1/100 sec) spent executing in user code.
4891             */
4892            long mUserTime;
4893
4894            /**
4895             * Total time (in 1/100 sec) spent executing in kernel code.
4896             */
4897            long mSystemTime;
4898
4899            /**
4900             * Amount of time the process was running in the foreground.
4901             */
4902            long mForegroundTime;
4903
4904            /**
4905             * Number of times the process has been started.
4906             */
4907            int mStarts;
4908
4909            /**
4910             * The amount of user time loaded from a previous save.
4911             */
4912            long mLoadedUserTime;
4913
4914            /**
4915             * The amount of system time loaded from a previous save.
4916             */
4917            long mLoadedSystemTime;
4918
4919            /**
4920             * The amount of foreground time loaded from a previous save.
4921             */
4922            long mLoadedForegroundTime;
4923
4924            /**
4925             * The number of times the process has started from a previous save.
4926             */
4927            int mLoadedStarts;
4928
4929            /**
4930             * The amount of user time loaded from the previous run.
4931             */
4932            long mLastUserTime;
4933
4934            /**
4935             * The amount of system time loaded from the previous run.
4936             */
4937            long mLastSystemTime;
4938
4939            /**
4940             * The amount of foreground time loaded from the previous run
4941             */
4942            long mLastForegroundTime;
4943
4944            /**
4945             * The number of times the process has started from the previous run.
4946             */
4947            int mLastStarts;
4948
4949            /**
4950             * The amount of user time when last unplugged.
4951             */
4952            long mUnpluggedUserTime;
4953
4954            /**
4955             * The amount of system time when last unplugged.
4956             */
4957            long mUnpluggedSystemTime;
4958
4959            /**
4960             * The amount of foreground time since unplugged.
4961             */
4962            long mUnpluggedForegroundTime;
4963
4964            /**
4965             * The number of times the process has started before unplugged.
4966             */
4967            int mUnpluggedStarts;
4968
4969            /**
4970             * Current process state.
4971             */
4972            int mProcessState = PROCESS_STATE_NONE;
4973
4974            SamplingCounter[] mSpeedBins;
4975
4976            ArrayList<ExcessivePower> mExcessivePower;
4977
4978            Proc() {
4979                mOnBatteryTimeBase.add(this);
4980                mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
4981            }
4982
4983            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
4984                mUnpluggedUserTime = mUserTime;
4985                mUnpluggedSystemTime = mSystemTime;
4986                mUnpluggedForegroundTime = mForegroundTime;
4987                mUnpluggedStarts = mStarts;
4988            }
4989
4990            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
4991            }
4992
4993            void detach() {
4994                mActive = false;
4995                mOnBatteryTimeBase.remove(this);
4996                for (int i = 0; i < mSpeedBins.length; i++) {
4997                    SamplingCounter c = mSpeedBins[i];
4998                    if (c != null) {
4999                        mOnBatteryTimeBase.remove(c);
5000                        mSpeedBins[i] = null;
5001                    }
5002                }
5003            }
5004
5005            public int countExcessivePowers() {
5006                return mExcessivePower != null ? mExcessivePower.size() : 0;
5007            }
5008
5009            public ExcessivePower getExcessivePower(int i) {
5010                if (mExcessivePower != null) {
5011                    return mExcessivePower.get(i);
5012                }
5013                return null;
5014            }
5015
5016            public void addExcessiveWake(long overTime, long usedTime) {
5017                if (mExcessivePower == null) {
5018                    mExcessivePower = new ArrayList<ExcessivePower>();
5019                }
5020                ExcessivePower ew = new ExcessivePower();
5021                ew.type = ExcessivePower.TYPE_WAKE;
5022                ew.overTime = overTime;
5023                ew.usedTime = usedTime;
5024                mExcessivePower.add(ew);
5025            }
5026
5027            public void addExcessiveCpu(long overTime, long usedTime) {
5028                if (mExcessivePower == null) {
5029                    mExcessivePower = new ArrayList<ExcessivePower>();
5030                }
5031                ExcessivePower ew = new ExcessivePower();
5032                ew.type = ExcessivePower.TYPE_CPU;
5033                ew.overTime = overTime;
5034                ew.usedTime = usedTime;
5035                mExcessivePower.add(ew);
5036            }
5037
5038            void writeExcessivePowerToParcelLocked(Parcel out) {
5039                if (mExcessivePower == null) {
5040                    out.writeInt(0);
5041                    return;
5042                }
5043
5044                final int N = mExcessivePower.size();
5045                out.writeInt(N);
5046                for (int i=0; i<N; i++) {
5047                    ExcessivePower ew = mExcessivePower.get(i);
5048                    out.writeInt(ew.type);
5049                    out.writeLong(ew.overTime);
5050                    out.writeLong(ew.usedTime);
5051                }
5052            }
5053
5054            boolean readExcessivePowerFromParcelLocked(Parcel in) {
5055                final int N = in.readInt();
5056                if (N == 0) {
5057                    mExcessivePower = null;
5058                    return true;
5059                }
5060
5061                if (N > 10000) {
5062                    Slog.w(TAG, "File corrupt: too many excessive power entries " + N);
5063                    return false;
5064                }
5065
5066                mExcessivePower = new ArrayList<ExcessivePower>();
5067                for (int i=0; i<N; i++) {
5068                    ExcessivePower ew = new ExcessivePower();
5069                    ew.type = in.readInt();
5070                    ew.overTime = in.readLong();
5071                    ew.usedTime = in.readLong();
5072                    mExcessivePower.add(ew);
5073                }
5074                return true;
5075            }
5076
5077            void writeToParcelLocked(Parcel out) {
5078                out.writeLong(mUserTime);
5079                out.writeLong(mSystemTime);
5080                out.writeLong(mForegroundTime);
5081                out.writeInt(mStarts);
5082                out.writeLong(mLoadedUserTime);
5083                out.writeLong(mLoadedSystemTime);
5084                out.writeLong(mLoadedForegroundTime);
5085                out.writeInt(mLoadedStarts);
5086                out.writeLong(mUnpluggedUserTime);
5087                out.writeLong(mUnpluggedSystemTime);
5088                out.writeLong(mUnpluggedForegroundTime);
5089                out.writeInt(mUnpluggedStarts);
5090
5091                out.writeInt(mSpeedBins.length);
5092                for (int i = 0; i < mSpeedBins.length; i++) {
5093                    SamplingCounter c = mSpeedBins[i];
5094                    if (c != null) {
5095                        out.writeInt(1);
5096                        c.writeToParcel(out);
5097                    } else {
5098                        out.writeInt(0);
5099                    }
5100                }
5101
5102                writeExcessivePowerToParcelLocked(out);
5103            }
5104
5105            void readFromParcelLocked(Parcel in) {
5106                mUserTime = in.readLong();
5107                mSystemTime = in.readLong();
5108                mForegroundTime = in.readLong();
5109                mStarts = in.readInt();
5110                mLoadedUserTime = in.readLong();
5111                mLoadedSystemTime = in.readLong();
5112                mLoadedForegroundTime = in.readLong();
5113                mLoadedStarts = in.readInt();
5114                mLastUserTime = 0;
5115                mLastSystemTime = 0;
5116                mLastForegroundTime = 0;
5117                mLastStarts = 0;
5118                mUnpluggedUserTime = in.readLong();
5119                mUnpluggedSystemTime = in.readLong();
5120                mUnpluggedForegroundTime = in.readLong();
5121                mUnpluggedStarts = in.readInt();
5122
5123                int bins = in.readInt();
5124                int steps = getCpuSpeedSteps();
5125                mSpeedBins = new SamplingCounter[bins >= steps ? bins : steps];
5126                for (int i = 0; i < bins; i++) {
5127                    if (in.readInt() != 0) {
5128                        mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase, in);
5129                    }
5130                }
5131
5132                readExcessivePowerFromParcelLocked(in);
5133            }
5134
5135            public BatteryStatsImpl getBatteryStats() {
5136                return BatteryStatsImpl.this;
5137            }
5138
5139            public void addCpuTimeLocked(int utime, int stime) {
5140                mUserTime += utime;
5141                mSystemTime += stime;
5142            }
5143
5144            public void addForegroundTimeLocked(long ttime) {
5145                mForegroundTime += ttime;
5146            }
5147
5148            public void incStartsLocked() {
5149                mStarts++;
5150            }
5151
5152            @Override
5153            public boolean isActive() {
5154                return mActive;
5155            }
5156
5157            @Override
5158            public long getUserTime(int which) {
5159                long val = mUserTime;
5160                if (which == STATS_CURRENT) {
5161                    val -= mLoadedUserTime;
5162                } else if (which == STATS_SINCE_UNPLUGGED) {
5163                    val -= mUnpluggedUserTime;
5164                }
5165                return val;
5166            }
5167
5168            @Override
5169            public long getSystemTime(int which) {
5170                long val = mSystemTime;
5171                if (which == STATS_CURRENT) {
5172                    val -= mLoadedSystemTime;
5173                } else if (which == STATS_SINCE_UNPLUGGED) {
5174                    val -= mUnpluggedSystemTime;
5175                }
5176                return val;
5177            }
5178
5179            @Override
5180            public long getForegroundTime(int which) {
5181                long val = mForegroundTime;
5182                if (which == STATS_CURRENT) {
5183                    val -= mLoadedForegroundTime;
5184                } else if (which == STATS_SINCE_UNPLUGGED) {
5185                    val -= mUnpluggedForegroundTime;
5186                }
5187                return val;
5188            }
5189
5190            @Override
5191            public int getStarts(int which) {
5192                int val = mStarts;
5193                if (which == STATS_CURRENT) {
5194                    val -= mLoadedStarts;
5195                } else if (which == STATS_SINCE_UNPLUGGED) {
5196                    val -= mUnpluggedStarts;
5197                }
5198                return val;
5199            }
5200
5201            /* Called by ActivityManagerService when CPU times are updated. */
5202            public void addSpeedStepTimes(long[] values) {
5203                for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
5204                    long amt = values[i];
5205                    if (amt != 0) {
5206                        SamplingCounter c = mSpeedBins[i];
5207                        if (c == null) {
5208                            mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
5209                        }
5210                        c.addCountAtomic(values[i]);
5211                    }
5212                }
5213            }
5214
5215            @Override
5216            public long getTimeAtCpuSpeedStep(int speedStep, int which) {
5217                if (speedStep < mSpeedBins.length) {
5218                    SamplingCounter c = mSpeedBins[speedStep];
5219                    return c != null ? c.getCountLocked(which) : 0;
5220                } else {
5221                    return 0;
5222                }
5223            }
5224        }
5225
5226        /**
5227         * The statistics associated with a particular package.
5228         */
5229        public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
5230            /**
5231             * Number of times this package has done something that could wake up the
5232             * device from sleep.
5233             */
5234            int mWakeups;
5235
5236            /**
5237             * Number of things that could wake up the device loaded from a
5238             * previous save.
5239             */
5240            int mLoadedWakeups;
5241
5242            /**
5243             * Number of things that could wake up the device as of the
5244             * last run.
5245             */
5246            int mLastWakeups;
5247
5248            /**
5249             * Number of things that could wake up the device as of the
5250             * last run.
5251             */
5252            int mUnpluggedWakeups;
5253
5254            /**
5255             * The statics we have collected for this package's services.
5256             */
5257            final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
5258
5259            Pkg() {
5260                mOnBatteryScreenOffTimeBase.add(this);
5261            }
5262
5263            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
5264                mUnpluggedWakeups = mWakeups;
5265            }
5266
5267            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
5268            }
5269
5270            void detach() {
5271                mOnBatteryScreenOffTimeBase.remove(this);
5272            }
5273
5274            void readFromParcelLocked(Parcel in) {
5275                mWakeups = in.readInt();
5276                mLoadedWakeups = in.readInt();
5277                mLastWakeups = 0;
5278                mUnpluggedWakeups = in.readInt();
5279
5280                int numServs = in.readInt();
5281                mServiceStats.clear();
5282                for (int m = 0; m < numServs; m++) {
5283                    String serviceName = in.readString();
5284                    Uid.Pkg.Serv serv = new Serv();
5285                    mServiceStats.put(serviceName, serv);
5286
5287                    serv.readFromParcelLocked(in);
5288                }
5289            }
5290
5291            void writeToParcelLocked(Parcel out) {
5292                out.writeInt(mWakeups);
5293                out.writeInt(mLoadedWakeups);
5294                out.writeInt(mUnpluggedWakeups);
5295
5296                out.writeInt(mServiceStats.size());
5297                for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
5298                    out.writeString(servEntry.getKey());
5299                    Uid.Pkg.Serv serv = servEntry.getValue();
5300
5301                    serv.writeToParcelLocked(out);
5302                }
5303            }
5304
5305            @Override
5306            public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
5307                return mServiceStats;
5308            }
5309
5310            @Override
5311            public int getWakeups(int which) {
5312                int val = mWakeups;
5313                if (which == STATS_CURRENT) {
5314                    val -= mLoadedWakeups;
5315                } else if (which == STATS_SINCE_UNPLUGGED) {
5316                    val -= mUnpluggedWakeups;
5317                }
5318
5319                return val;
5320            }
5321
5322            /**
5323             * The statistics associated with a particular service.
5324             */
5325            public final class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
5326                /**
5327                 * Total time (ms in battery uptime) the service has been left started.
5328                 */
5329                long mStartTime;
5330
5331                /**
5332                 * If service has been started and not yet stopped, this is
5333                 * when it was started.
5334                 */
5335                long mRunningSince;
5336
5337                /**
5338                 * True if we are currently running.
5339                 */
5340                boolean mRunning;
5341
5342                /**
5343                 * Total number of times startService() has been called.
5344                 */
5345                int mStarts;
5346
5347                /**
5348                 * Total time (ms in battery uptime) the service has been left launched.
5349                 */
5350                long mLaunchedTime;
5351
5352                /**
5353                 * If service has been launched and not yet exited, this is
5354                 * when it was launched (ms in battery uptime).
5355                 */
5356                long mLaunchedSince;
5357
5358                /**
5359                 * True if we are currently launched.
5360                 */
5361                boolean mLaunched;
5362
5363                /**
5364                 * Total number times the service has been launched.
5365                 */
5366                int mLaunches;
5367
5368                /**
5369                 * The amount of time spent started loaded from a previous save
5370                 * (ms in battery uptime).
5371                 */
5372                long mLoadedStartTime;
5373
5374                /**
5375                 * The number of starts loaded from a previous save.
5376                 */
5377                int mLoadedStarts;
5378
5379                /**
5380                 * The number of launches loaded from a previous save.
5381                 */
5382                int mLoadedLaunches;
5383
5384                /**
5385                 * The amount of time spent started as of the last run (ms
5386                 * in battery uptime).
5387                 */
5388                long mLastStartTime;
5389
5390                /**
5391                 * The number of starts as of the last run.
5392                 */
5393                int mLastStarts;
5394
5395                /**
5396                 * The number of launches as of the last run.
5397                 */
5398                int mLastLaunches;
5399
5400                /**
5401                 * The amount of time spent started when last unplugged (ms
5402                 * in battery uptime).
5403                 */
5404                long mUnpluggedStartTime;
5405
5406                /**
5407                 * The number of starts when last unplugged.
5408                 */
5409                int mUnpluggedStarts;
5410
5411                /**
5412                 * The number of launches when last unplugged.
5413                 */
5414                int mUnpluggedLaunches;
5415
5416                Serv() {
5417                    mOnBatteryTimeBase.add(this);
5418                }
5419
5420                public void onTimeStarted(long elapsedRealtime, long baseUptime,
5421                        long baseRealtime) {
5422                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
5423                    mUnpluggedStarts = mStarts;
5424                    mUnpluggedLaunches = mLaunches;
5425                }
5426
5427                public void onTimeStopped(long elapsedRealtime, long baseUptime,
5428                        long baseRealtime) {
5429                }
5430
5431                void detach() {
5432                    mOnBatteryTimeBase.remove(this);
5433                }
5434
5435                void readFromParcelLocked(Parcel in) {
5436                    mStartTime = in.readLong();
5437                    mRunningSince = in.readLong();
5438                    mRunning = in.readInt() != 0;
5439                    mStarts = in.readInt();
5440                    mLaunchedTime = in.readLong();
5441                    mLaunchedSince = in.readLong();
5442                    mLaunched = in.readInt() != 0;
5443                    mLaunches = in.readInt();
5444                    mLoadedStartTime = in.readLong();
5445                    mLoadedStarts = in.readInt();
5446                    mLoadedLaunches = in.readInt();
5447                    mLastStartTime = 0;
5448                    mLastStarts = 0;
5449                    mLastLaunches = 0;
5450                    mUnpluggedStartTime = in.readLong();
5451                    mUnpluggedStarts = in.readInt();
5452                    mUnpluggedLaunches = in.readInt();
5453                }
5454
5455                void writeToParcelLocked(Parcel out) {
5456                    out.writeLong(mStartTime);
5457                    out.writeLong(mRunningSince);
5458                    out.writeInt(mRunning ? 1 : 0);
5459                    out.writeInt(mStarts);
5460                    out.writeLong(mLaunchedTime);
5461                    out.writeLong(mLaunchedSince);
5462                    out.writeInt(mLaunched ? 1 : 0);
5463                    out.writeInt(mLaunches);
5464                    out.writeLong(mLoadedStartTime);
5465                    out.writeInt(mLoadedStarts);
5466                    out.writeInt(mLoadedLaunches);
5467                    out.writeLong(mUnpluggedStartTime);
5468                    out.writeInt(mUnpluggedStarts);
5469                    out.writeInt(mUnpluggedLaunches);
5470                }
5471
5472                long getLaunchTimeToNowLocked(long batteryUptime) {
5473                    if (!mLaunched) return mLaunchedTime;
5474                    return mLaunchedTime + batteryUptime - mLaunchedSince;
5475                }
5476
5477                long getStartTimeToNowLocked(long batteryUptime) {
5478                    if (!mRunning) return mStartTime;
5479                    return mStartTime + batteryUptime - mRunningSince;
5480                }
5481
5482                public void startLaunchedLocked() {
5483                    if (!mLaunched) {
5484                        mLaunches++;
5485                        mLaunchedSince = getBatteryUptimeLocked();
5486                        mLaunched = true;
5487                    }
5488                }
5489
5490                public void stopLaunchedLocked() {
5491                    if (mLaunched) {
5492                        long time = getBatteryUptimeLocked() - mLaunchedSince;
5493                        if (time > 0) {
5494                            mLaunchedTime += time;
5495                        } else {
5496                            mLaunches--;
5497                        }
5498                        mLaunched = false;
5499                    }
5500                }
5501
5502                public void startRunningLocked() {
5503                    if (!mRunning) {
5504                        mStarts++;
5505                        mRunningSince = getBatteryUptimeLocked();
5506                        mRunning = true;
5507                    }
5508                }
5509
5510                public void stopRunningLocked() {
5511                    if (mRunning) {
5512                        long time = getBatteryUptimeLocked() - mRunningSince;
5513                        if (time > 0) {
5514                            mStartTime += time;
5515                        } else {
5516                            mStarts--;
5517                        }
5518                        mRunning = false;
5519                    }
5520                }
5521
5522                public BatteryStatsImpl getBatteryStats() {
5523                    return BatteryStatsImpl.this;
5524                }
5525
5526                @Override
5527                public int getLaunches(int which) {
5528                    int val = mLaunches;
5529                    if (which == STATS_CURRENT) {
5530                        val -= mLoadedLaunches;
5531                    } else if (which == STATS_SINCE_UNPLUGGED) {
5532                        val -= mUnpluggedLaunches;
5533                    }
5534                    return val;
5535                }
5536
5537                @Override
5538                public long getStartTime(long now, int which) {
5539                    long val = getStartTimeToNowLocked(now);
5540                    if (which == STATS_CURRENT) {
5541                        val -= mLoadedStartTime;
5542                    } else if (which == STATS_SINCE_UNPLUGGED) {
5543                        val -= mUnpluggedStartTime;
5544                    }
5545                    return val;
5546                }
5547
5548                @Override
5549                public int getStarts(int which) {
5550                    int val = mStarts;
5551                    if (which == STATS_CURRENT) {
5552                        val -= mLoadedStarts;
5553                    } else if (which == STATS_SINCE_UNPLUGGED) {
5554                        val -= mUnpluggedStarts;
5555                    }
5556
5557                    return val;
5558                }
5559            }
5560
5561            public BatteryStatsImpl getBatteryStats() {
5562                return BatteryStatsImpl.this;
5563            }
5564
5565            public void incWakeupsLocked() {
5566                mWakeups++;
5567            }
5568
5569            final Serv newServiceStatsLocked() {
5570                return new Serv();
5571            }
5572        }
5573
5574        /**
5575         * Retrieve the statistics object for a particular process, creating
5576         * if needed.
5577         */
5578        public Proc getProcessStatsLocked(String name) {
5579            Proc ps = mProcessStats.get(name);
5580            if (ps == null) {
5581                ps = new Proc();
5582                mProcessStats.put(name, ps);
5583            }
5584
5585            return ps;
5586        }
5587
5588        public void updateProcessStateLocked(String procName, int state, long elapsedRealtimeMs) {
5589            int procState;
5590            if (state <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
5591                procState = PROCESS_STATE_FOREGROUND;
5592            } else if (state <= ActivityManager.PROCESS_STATE_RECEIVER) {
5593                procState = PROCESS_STATE_ACTIVE;
5594            } else {
5595                procState = PROCESS_STATE_RUNNING;
5596            }
5597            updateRealProcessStateLocked(procName, procState, elapsedRealtimeMs);
5598        }
5599
5600        public void updateRealProcessStateLocked(String procName, int procState,
5601                long elapsedRealtimeMs) {
5602            Proc proc = getProcessStatsLocked(procName);
5603            if (proc.mProcessState != procState) {
5604                boolean changed;
5605                if (procState < proc.mProcessState) {
5606                    // Has this process become more important?  If so,
5607                    // we may need to change the uid if the currrent uid proc state
5608                    // is not as important as what we are now setting.
5609                    changed = mProcessState > procState;
5610                } else {
5611                    // Has this process become less important?  If so,
5612                    // we may need to change the uid if the current uid proc state
5613                    // is the same importance as the old setting.
5614                    changed = mProcessState == proc.mProcessState;
5615                }
5616                proc.mProcessState = procState;
5617                if (changed) {
5618                    // uid's state may have changed; compute what the new state should be.
5619                    int uidProcState = PROCESS_STATE_NONE;
5620                    for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
5621                        proc = mProcessStats.valueAt(ip);
5622                        if (proc.mProcessState < uidProcState) {
5623                            uidProcState = proc.mProcessState;
5624                        }
5625                    }
5626                    updateUidProcessStateLocked(uidProcState, elapsedRealtimeMs);
5627                }
5628            }
5629        }
5630
5631        public SparseArray<? extends Pid> getPidStats() {
5632            return mPids;
5633        }
5634
5635        public Pid getPidStatsLocked(int pid) {
5636            Pid p = mPids.get(pid);
5637            if (p == null) {
5638                p = new Pid();
5639                mPids.put(pid, p);
5640            }
5641            return p;
5642        }
5643
5644        /**
5645         * Retrieve the statistics object for a particular service, creating
5646         * if needed.
5647         */
5648        public Pkg getPackageStatsLocked(String name) {
5649            Pkg ps = mPackageStats.get(name);
5650            if (ps == null) {
5651                ps = new Pkg();
5652                mPackageStats.put(name, ps);
5653            }
5654
5655            return ps;
5656        }
5657
5658        /**
5659         * Retrieve the statistics object for a particular service, creating
5660         * if needed.
5661         */
5662        public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
5663            Pkg ps = getPackageStatsLocked(pkg);
5664            Pkg.Serv ss = ps.mServiceStats.get(serv);
5665            if (ss == null) {
5666                ss = ps.newServiceStatsLocked();
5667                ps.mServiceStats.put(serv, ss);
5668            }
5669
5670            return ss;
5671        }
5672
5673        public StopwatchTimer getWakeTimerLocked(String name, int type) {
5674            Wakelock wl = mWakelockStats.get(name);
5675            if (wl == null) {
5676                final int N = mWakelockStats.size();
5677                if (N > MAX_WAKELOCKS_PER_UID) {
5678                    name = BATCHED_WAKELOCK_NAME;
5679                    wl = mWakelockStats.get(name);
5680                }
5681                if (wl == null) {
5682                    wl = new Wakelock();
5683                    mWakelockStats.put(name, wl);
5684                }
5685            }
5686            StopwatchTimer t = null;
5687            switch (type) {
5688                case WAKE_TYPE_PARTIAL:
5689                    t = wl.mTimerPartial;
5690                    if (t == null) {
5691                        t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
5692                                mPartialTimers, mOnBatteryScreenOffTimeBase);
5693                        wl.mTimerPartial = t;
5694                    }
5695                    return t;
5696                case WAKE_TYPE_FULL:
5697                    t = wl.mTimerFull;
5698                    if (t == null) {
5699                        t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
5700                                mFullTimers, mOnBatteryTimeBase);
5701                        wl.mTimerFull = t;
5702                    }
5703                    return t;
5704                case WAKE_TYPE_WINDOW:
5705                    t = wl.mTimerWindow;
5706                    if (t == null) {
5707                        t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
5708                                mWindowTimers, mOnBatteryTimeBase);
5709                        wl.mTimerWindow = t;
5710                    }
5711                    return t;
5712                default:
5713                    throw new IllegalArgumentException("type=" + type);
5714            }
5715        }
5716
5717        public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
5718            Sensor se = mSensorStats.get(sensor);
5719            if (se == null) {
5720                if (!create) {
5721                    return null;
5722                }
5723                se = new Sensor(sensor);
5724                mSensorStats.put(sensor, se);
5725            }
5726            StopwatchTimer t = se.mTimer;
5727            if (t != null) {
5728                return t;
5729            }
5730            ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
5731            if (timers == null) {
5732                timers = new ArrayList<StopwatchTimer>();
5733                mSensorTimers.put(sensor, timers);
5734            }
5735            t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mOnBatteryTimeBase);
5736            se.mTimer = t;
5737            return t;
5738        }
5739
5740        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
5741            StopwatchTimer t = getWakeTimerLocked(name, type);
5742            if (t != null) {
5743                t.startRunningLocked(elapsedRealtimeMs);
5744            }
5745            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
5746                Pid p = getPidStatsLocked(pid);
5747                if (p.mWakeNesting++ == 0) {
5748                    p.mWakeStartMs = elapsedRealtimeMs;
5749                }
5750            }
5751        }
5752
5753        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
5754            StopwatchTimer t = getWakeTimerLocked(name, type);
5755            if (t != null) {
5756                t.stopRunningLocked(elapsedRealtimeMs);
5757            }
5758            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
5759                Pid p = mPids.get(pid);
5760                if (p != null && p.mWakeNesting > 0) {
5761                    if (p.mWakeNesting-- == 1) {
5762                        p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
5763                        p.mWakeStartMs = 0;
5764                    }
5765                }
5766            }
5767        }
5768
5769        public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
5770            Proc p = getProcessStatsLocked(proc);
5771            if (p != null) {
5772                p.addExcessiveWake(overTime, usedTime);
5773            }
5774        }
5775
5776        public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
5777            Proc p = getProcessStatsLocked(proc);
5778            if (p != null) {
5779                p.addExcessiveCpu(overTime, usedTime);
5780            }
5781        }
5782
5783        public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
5784            StopwatchTimer t = getSensorTimerLocked(sensor, true);
5785            if (t != null) {
5786                t.startRunningLocked(elapsedRealtimeMs);
5787            }
5788        }
5789
5790        public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
5791            // Don't create a timer if one doesn't already exist
5792            StopwatchTimer t = getSensorTimerLocked(sensor, false);
5793            if (t != null) {
5794                t.stopRunningLocked(elapsedRealtimeMs);
5795            }
5796        }
5797
5798        public void noteStartGps(long elapsedRealtimeMs) {
5799            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
5800            if (t != null) {
5801                t.startRunningLocked(elapsedRealtimeMs);
5802            }
5803        }
5804
5805        public void noteStopGps(long elapsedRealtimeMs) {
5806            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
5807            if (t != null) {
5808                t.stopRunningLocked(elapsedRealtimeMs);
5809            }
5810        }
5811
5812        public BatteryStatsImpl getBatteryStats() {
5813            return BatteryStatsImpl.this;
5814        }
5815    }
5816
5817    public BatteryStatsImpl(String filename, Handler handler) {
5818        mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
5819        mHandler = new MyHandler(handler.getLooper());
5820        mStartCount++;
5821        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
5822        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
5823            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
5824        }
5825        mInteractiveTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
5826        mLowPowerModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
5827        mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
5828        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
5829            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
5830                    mOnBatteryTimeBase);
5831        }
5832        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase);
5833        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
5834            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null,
5835                    mOnBatteryTimeBase);
5836        }
5837        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5838            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
5839            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
5840        }
5841        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
5842        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
5843        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
5844        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
5845        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
5846        mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase);
5847        mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase);
5848        for (int i=0; i<NUM_WIFI_STATES; i++) {
5849            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mOnBatteryTimeBase);
5850        }
5851        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
5852            mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i, null, mOnBatteryTimeBase);
5853        }
5854        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
5855            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i, null,
5856                    mOnBatteryTimeBase);
5857        }
5858        mBluetoothOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
5859        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
5860            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mOnBatteryTimeBase);
5861        }
5862        mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
5863        mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
5864        mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
5865        mOnBattery = mOnBatteryInternal = false;
5866        long uptime = SystemClock.uptimeMillis() * 1000;
5867        long realtime = SystemClock.elapsedRealtime() * 1000;
5868        initTimes(uptime, realtime);
5869        mDischargeStartLevel = 0;
5870        mDischargeUnplugLevel = 0;
5871        mDischargePlugLevel = -1;
5872        mDischargeCurrentLevel = 0;
5873        mCurrentBatteryLevel = 0;
5874        initDischarge();
5875        clearHistoryLocked();
5876    }
5877
5878    public BatteryStatsImpl(Parcel p) {
5879        mFile = null;
5880        mHandler = null;
5881        clearHistoryLocked();
5882        readFromParcel(p);
5883    }
5884
5885    public void setCallback(BatteryCallback cb) {
5886        mCallback = cb;
5887    }
5888
5889    public void setNumSpeedSteps(int steps) {
5890        if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
5891    }
5892
5893    public void setRadioScanningTimeout(long timeout) {
5894        if (mPhoneSignalScanningTimer != null) {
5895            mPhoneSignalScanningTimer.setTimeout(timeout);
5896        }
5897    }
5898
5899    @Override
5900    public boolean startIteratingOldHistoryLocked() {
5901        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
5902                + " pos=" + mHistoryBuffer.dataPosition());
5903        if ((mHistoryIterator = mHistory) == null) {
5904            return false;
5905        }
5906        mHistoryBuffer.setDataPosition(0);
5907        mHistoryReadTmp.clear();
5908        mReadOverflow = false;
5909        mIteratingHistory = true;
5910        return true;
5911    }
5912
5913    @Override
5914    public boolean getNextOldHistoryLocked(HistoryItem out) {
5915        boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
5916        if (!end) {
5917            readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
5918            mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
5919        }
5920        HistoryItem cur = mHistoryIterator;
5921        if (cur == null) {
5922            if (!mReadOverflow && !end) {
5923                Slog.w(TAG, "Old history ends before new history!");
5924            }
5925            return false;
5926        }
5927        out.setTo(cur);
5928        mHistoryIterator = cur.next;
5929        if (!mReadOverflow) {
5930            if (end) {
5931                Slog.w(TAG, "New history ends before old history!");
5932            } else if (!out.same(mHistoryReadTmp)) {
5933                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
5934                pw.println("Histories differ!");
5935                pw.println("Old history:");
5936                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
5937                pw.println("New history:");
5938                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
5939                        true);
5940                pw.flush();
5941            }
5942        }
5943        return true;
5944    }
5945
5946    @Override
5947    public void finishIteratingOldHistoryLocked() {
5948        mIteratingHistory = false;
5949        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
5950        mHistoryIterator = null;
5951    }
5952
5953    public int getHistoryTotalSize() {
5954        return MAX_HISTORY_BUFFER;
5955    }
5956
5957    public int getHistoryUsedSize() {
5958        return mHistoryBuffer.dataSize();
5959    }
5960
5961    @Override
5962    public boolean startIteratingHistoryLocked() {
5963        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
5964                + " pos=" + mHistoryBuffer.dataPosition());
5965        if (mHistoryBuffer.dataSize() <= 0) {
5966            return false;
5967        }
5968        mHistoryBuffer.setDataPosition(0);
5969        mReadOverflow = false;
5970        mIteratingHistory = true;
5971        mReadHistoryStrings = new String[mHistoryTagPool.size()];
5972        mReadHistoryUids = new int[mHistoryTagPool.size()];
5973        mReadHistoryChars = 0;
5974        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
5975            final HistoryTag tag = ent.getKey();
5976            final int idx = ent.getValue();
5977            mReadHistoryStrings[idx] = tag.string;
5978            mReadHistoryUids[idx] = tag.uid;
5979            mReadHistoryChars += tag.string.length() + 1;
5980        }
5981        return true;
5982    }
5983
5984    @Override
5985    public int getHistoryStringPoolSize() {
5986        return mReadHistoryStrings.length;
5987    }
5988
5989    @Override
5990    public int getHistoryStringPoolBytes() {
5991        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
5992        // Each string character is 2 bytes.
5993        return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
5994    }
5995
5996    @Override
5997    public String getHistoryTagPoolString(int index) {
5998        return mReadHistoryStrings[index];
5999    }
6000
6001    @Override
6002    public int getHistoryTagPoolUid(int index) {
6003        return mReadHistoryUids[index];
6004    }
6005
6006    @Override
6007    public boolean getNextHistoryLocked(HistoryItem out) {
6008        final int pos = mHistoryBuffer.dataPosition();
6009        if (pos == 0) {
6010            out.clear();
6011        }
6012        boolean end = pos >= mHistoryBuffer.dataSize();
6013        if (end) {
6014            return false;
6015        }
6016
6017        final long lastRealtime = out.time;
6018        final long lastWalltime = out.currentTime;
6019        readHistoryDelta(mHistoryBuffer, out);
6020        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
6021                && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
6022            out.currentTime = lastWalltime + (out.time - lastRealtime);
6023        }
6024        return true;
6025    }
6026
6027    @Override
6028    public void finishIteratingHistoryLocked() {
6029        mIteratingHistory = false;
6030        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
6031        mReadHistoryStrings = null;
6032    }
6033
6034    @Override
6035    public long getHistoryBaseTime() {
6036        return mHistoryBaseTime;
6037    }
6038
6039    @Override
6040    public int getStartCount() {
6041        return mStartCount;
6042    }
6043
6044    public boolean isOnBattery() {
6045        return mOnBattery;
6046    }
6047
6048    public boolean isScreenOn() {
6049        return mScreenState == Display.STATE_ON;
6050    }
6051
6052    void initTimes(long uptime, long realtime) {
6053        mStartClockTime = System.currentTimeMillis();
6054        mOnBatteryTimeBase.init(uptime, realtime);
6055        mOnBatteryScreenOffTimeBase.init(uptime, realtime);
6056        mRealtime = 0;
6057        mUptime = 0;
6058        mRealtimeStart = realtime;
6059        mUptimeStart = uptime;
6060    }
6061
6062    void initDischarge() {
6063        mLowDischargeAmountSinceCharge = 0;
6064        mHighDischargeAmountSinceCharge = 0;
6065        mDischargeAmountScreenOn = 0;
6066        mDischargeAmountScreenOnSinceCharge = 0;
6067        mDischargeAmountScreenOff = 0;
6068        mDischargeAmountScreenOffSinceCharge = 0;
6069        mLastDischargeStepTime = -1;
6070        mNumDischargeStepDurations = 0;
6071        mLastChargeStepTime = -1;
6072        mNumChargeStepDurations = 0;
6073    }
6074
6075    public void resetAllStatsCmdLocked() {
6076        resetAllStatsLocked();
6077        final long mSecUptime = SystemClock.uptimeMillis();
6078        long uptime = mSecUptime * 1000;
6079        long mSecRealtime = SystemClock.elapsedRealtime();
6080        long realtime = mSecRealtime * 1000;
6081        mDischargeStartLevel = mHistoryCur.batteryLevel;
6082        pullPendingStateUpdatesLocked();
6083        addHistoryRecordLocked(mSecRealtime, mSecUptime);
6084        mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
6085                = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
6086        mOnBatteryTimeBase.reset(uptime, realtime);
6087        mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
6088        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
6089            if (mScreenState == Display.STATE_ON) {
6090                mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
6091                mDischargeScreenOffUnplugLevel = 0;
6092            } else {
6093                mDischargeScreenOnUnplugLevel = 0;
6094                mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
6095            }
6096            mDischargeAmountScreenOn = 0;
6097            mDischargeAmountScreenOff = 0;
6098        }
6099        initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
6100    }
6101
6102    private void resetAllStatsLocked() {
6103        mStartCount = 0;
6104        initTimes(SystemClock.uptimeMillis() * 1000, SystemClock.elapsedRealtime() * 1000);
6105        mScreenOnTimer.reset(false);
6106        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
6107            mScreenBrightnessTimer[i].reset(false);
6108        }
6109        mInteractiveTimer.reset(false);
6110        mLowPowerModeEnabledTimer.reset(false);
6111        mPhoneOnTimer.reset(false);
6112        mAudioOnTimer.reset(false);
6113        mVideoOnTimer.reset(false);
6114        mFlashlightOnTimer.reset(false);
6115        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
6116            mPhoneSignalStrengthsTimer[i].reset(false);
6117        }
6118        mPhoneSignalScanningTimer.reset(false);
6119        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
6120            mPhoneDataConnectionsTimer[i].reset(false);
6121        }
6122        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6123            mNetworkByteActivityCounters[i].reset(false);
6124            mNetworkPacketActivityCounters[i].reset(false);
6125        }
6126        mMobileRadioActiveTimer.reset(false);
6127        mMobileRadioActivePerAppTimer.reset(false);
6128        mMobileRadioActiveAdjustedTime.reset(false);
6129        mMobileRadioActiveUnknownTime.reset(false);
6130        mMobileRadioActiveUnknownCount.reset(false);
6131        mWifiOnTimer.reset(false);
6132        mGlobalWifiRunningTimer.reset(false);
6133        for (int i=0; i<NUM_WIFI_STATES; i++) {
6134            mWifiStateTimer[i].reset(false);
6135        }
6136        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
6137            mWifiSupplStateTimer[i].reset(false);
6138        }
6139        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
6140            mWifiSignalStrengthsTimer[i].reset(false);
6141        }
6142        mBluetoothOnTimer.reset(false);
6143        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
6144            mBluetoothStateTimer[i].reset(false);
6145        }
6146
6147        for (int i=0; i<mUidStats.size(); i++) {
6148            if (mUidStats.valueAt(i).reset()) {
6149                mUidStats.remove(mUidStats.keyAt(i));
6150                i--;
6151            }
6152        }
6153
6154        if (mKernelWakelockStats.size() > 0) {
6155            for (SamplingTimer timer : mKernelWakelockStats.values()) {
6156                mOnBatteryScreenOffTimeBase.remove(timer);
6157            }
6158            mKernelWakelockStats.clear();
6159        }
6160
6161        if (mWakeupReasonStats.size() > 0) {
6162            for (LongSamplingCounter timer : mWakeupReasonStats.values()) {
6163                mOnBatteryScreenOffTimeBase.remove(timer);
6164            }
6165            mWakeupReasonStats.clear();
6166        }
6167
6168        initDischarge();
6169
6170        clearHistoryLocked();
6171    }
6172
6173    private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
6174        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
6175            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
6176            if (active == null) {
6177                continue;
6178            }
6179            for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
6180                SparseIntArray uids = ent.getValue();
6181                for (int j=0; j<uids.size(); j++) {
6182                    addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
6183                            uids.keyAt(j));
6184                }
6185            }
6186        }
6187    }
6188
6189    void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
6190        if (oldScreenOn) {
6191            int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
6192            if (diff > 0) {
6193                mDischargeAmountScreenOn += diff;
6194                mDischargeAmountScreenOnSinceCharge += diff;
6195            }
6196        } else {
6197            int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
6198            if (diff > 0) {
6199                mDischargeAmountScreenOff += diff;
6200                mDischargeAmountScreenOffSinceCharge += diff;
6201            }
6202        }
6203        if (newScreenOn) {
6204            mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
6205            mDischargeScreenOffUnplugLevel = 0;
6206        } else {
6207            mDischargeScreenOnUnplugLevel = 0;
6208            mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
6209        }
6210    }
6211
6212    public void pullPendingStateUpdatesLocked() {
6213        updateKernelWakelocksLocked();
6214        updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
6215        if (mOnBatteryInternal) {
6216            final boolean screenOn = mScreenState == Display.STATE_ON;
6217            updateDischargeScreenLevelsLocked(screenOn, screenOn);
6218        }
6219    }
6220
6221    void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
6222            final int oldStatus, final int level) {
6223        boolean doWrite = false;
6224        Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
6225        m.arg1 = onBattery ? 1 : 0;
6226        mHandler.sendMessage(m);
6227        mOnBattery = mOnBatteryInternal = onBattery;
6228
6229        final long uptime = mSecUptime * 1000;
6230        final long realtime = mSecRealtime * 1000;
6231        final boolean screenOn = mScreenState == Display.STATE_ON;
6232        if (onBattery) {
6233            // We will reset our status if we are unplugging after the
6234            // battery was last full, or the level is at 100, or
6235            // we have gone through a significant charge (from a very low
6236            // level to a now very high level).
6237            boolean reset = false;
6238            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
6239                    || level >= 90
6240                    || (mDischargeCurrentLevel < 20 && level >= 80))) {
6241                doWrite = true;
6242                resetAllStatsLocked();
6243                mDischargeStartLevel = level;
6244                reset = true;
6245                mNumDischargeStepDurations = 0;
6246            }
6247            mLastDischargeStepLevel = level;
6248            mMinDischargeStepLevel = level;
6249            mLastDischargeStepTime = -1;
6250            pullPendingStateUpdatesLocked();
6251            mHistoryCur.batteryLevel = (byte)level;
6252            mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
6253            if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
6254                    + Integer.toHexString(mHistoryCur.states));
6255            if (reset) {
6256                mRecordingHistory = true;
6257                startRecordingHistory(mSecRealtime, mSecUptime, reset);
6258            }
6259            addHistoryRecordLocked(mSecRealtime, mSecUptime);
6260            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
6261            if (screenOn) {
6262                mDischargeScreenOnUnplugLevel = level;
6263                mDischargeScreenOffUnplugLevel = 0;
6264            } else {
6265                mDischargeScreenOnUnplugLevel = 0;
6266                mDischargeScreenOffUnplugLevel = level;
6267            }
6268            mDischargeAmountScreenOn = 0;
6269            mDischargeAmountScreenOff = 0;
6270            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
6271        } else {
6272            pullPendingStateUpdatesLocked();
6273            mHistoryCur.batteryLevel = (byte)level;
6274            mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
6275            if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
6276                    + Integer.toHexString(mHistoryCur.states));
6277            addHistoryRecordLocked(mSecRealtime, mSecUptime);
6278            mDischargeCurrentLevel = mDischargePlugLevel = level;
6279            if (level < mDischargeUnplugLevel) {
6280                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
6281                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
6282            }
6283            updateDischargeScreenLevelsLocked(screenOn, screenOn);
6284            updateTimeBasesLocked(false, !screenOn, uptime, realtime);
6285            mNumChargeStepDurations = 0;
6286            mLastChargeStepLevel = level;
6287            mMaxChargeStepLevel = level;
6288            mLastChargeStepTime = -1;
6289        }
6290        if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
6291            if (mFile != null) {
6292                writeAsyncLocked();
6293            }
6294        }
6295    }
6296
6297    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
6298            boolean reset) {
6299        mRecordingHistory = true;
6300        mHistoryCur.currentTime = System.currentTimeMillis();
6301        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
6302                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
6303                mHistoryCur);
6304        mHistoryCur.currentTime = 0;
6305        if (reset) {
6306            initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
6307        }
6308    }
6309
6310    // This should probably be exposed in the API, though it's not critical
6311    private static final int BATTERY_PLUGGED_NONE = 0;
6312
6313    private static int addLevelSteps(long[] steps, int stepCount, long lastStepTime,
6314            int numStepLevels, long elapsedRealtime) {
6315        if (lastStepTime >= 0 && numStepLevels > 0) {
6316            long duration = elapsedRealtime - lastStepTime;
6317            for (int i=0; i<numStepLevels; i++) {
6318                System.arraycopy(steps, 0, steps, 1, steps.length-1);
6319                long thisDuration = duration / (numStepLevels-i);
6320                duration -= thisDuration;
6321                steps[0] = thisDuration;
6322            }
6323            stepCount += numStepLevels;
6324            if (stepCount > steps.length) {
6325                stepCount = steps.length;
6326            }
6327        }
6328        return stepCount;
6329    }
6330
6331    public void setBatteryState(int status, int health, int plugType, int level,
6332            int temp, int volt) {
6333        synchronized(this) {
6334            final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
6335            final long uptime = SystemClock.uptimeMillis();
6336            final long elapsedRealtime = SystemClock.elapsedRealtime();
6337            int oldStatus = mHistoryCur.batteryStatus;
6338            if (!mHaveBatteryLevel) {
6339                mHaveBatteryLevel = true;
6340                // We start out assuming that the device is plugged in (not
6341                // on battery).  If our first report is now that we are indeed
6342                // plugged in, then twiddle our state to correctly reflect that
6343                // since we won't be going through the full setOnBattery().
6344                if (onBattery == mOnBattery) {
6345                    if (onBattery) {
6346                        mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
6347                    } else {
6348                        mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
6349                    }
6350                }
6351                oldStatus = status;
6352            }
6353            if (onBattery) {
6354                mDischargeCurrentLevel = level;
6355                if (!mRecordingHistory) {
6356                    mRecordingHistory = true;
6357                    startRecordingHistory(elapsedRealtime, uptime, true);
6358                }
6359            } else if (level < 96) {
6360                if (!mRecordingHistory) {
6361                    mRecordingHistory = true;
6362                    startRecordingHistory(elapsedRealtime, uptime, true);
6363                }
6364            }
6365            mCurrentBatteryLevel = level;
6366            if (mDischargePlugLevel < 0) {
6367                mDischargePlugLevel = level;
6368            }
6369            if (onBattery != mOnBattery) {
6370                mHistoryCur.batteryLevel = (byte)level;
6371                mHistoryCur.batteryStatus = (byte)status;
6372                mHistoryCur.batteryHealth = (byte)health;
6373                mHistoryCur.batteryPlugType = (byte)plugType;
6374                mHistoryCur.batteryTemperature = (short)temp;
6375                mHistoryCur.batteryVoltage = (char)volt;
6376                setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
6377            } else {
6378                boolean changed = false;
6379                if (mHistoryCur.batteryLevel != level) {
6380                    mHistoryCur.batteryLevel = (byte)level;
6381                    changed = true;
6382                }
6383                if (mHistoryCur.batteryStatus != status) {
6384                    mHistoryCur.batteryStatus = (byte)status;
6385                    changed = true;
6386                }
6387                if (mHistoryCur.batteryHealth != health) {
6388                    mHistoryCur.batteryHealth = (byte)health;
6389                    changed = true;
6390                }
6391                if (mHistoryCur.batteryPlugType != plugType) {
6392                    mHistoryCur.batteryPlugType = (byte)plugType;
6393                    changed = true;
6394                }
6395                if (temp >= (mHistoryCur.batteryTemperature+10)
6396                        || temp <= (mHistoryCur.batteryTemperature-10)) {
6397                    mHistoryCur.batteryTemperature = (short)temp;
6398                    changed = true;
6399                }
6400                if (volt > (mHistoryCur.batteryVoltage+20)
6401                        || volt < (mHistoryCur.batteryVoltage-20)) {
6402                    mHistoryCur.batteryVoltage = (char)volt;
6403                    changed = true;
6404                }
6405                if (changed) {
6406                    addHistoryRecordLocked(elapsedRealtime, uptime);
6407                }
6408                if (onBattery) {
6409                    if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
6410                        mNumDischargeStepDurations = addLevelSteps(mDischargeStepDurations,
6411                                mNumDischargeStepDurations, mLastDischargeStepTime,
6412                                mLastDischargeStepLevel - level, elapsedRealtime);
6413                        mLastDischargeStepLevel = level;
6414                        mMinDischargeStepLevel = level;
6415                        mLastDischargeStepTime = elapsedRealtime;
6416                    }
6417                } else {
6418                    if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
6419                        mNumChargeStepDurations = addLevelSteps(mChargeStepDurations,
6420                                mNumChargeStepDurations, mLastChargeStepTime,
6421                                level - mLastChargeStepLevel, elapsedRealtime);
6422                        mLastChargeStepLevel = level;
6423                        mMaxChargeStepLevel = level;
6424                        mLastChargeStepTime = elapsedRealtime;
6425                    }
6426                }
6427            }
6428            if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
6429                // We don't record history while we are plugged in and fully charged.
6430                // The next time we are unplugged, history will be cleared.
6431                mRecordingHistory = DEBUG;
6432            }
6433        }
6434    }
6435
6436    public void updateKernelWakelocksLocked() {
6437        Map<String, KernelWakelockStats> m = readKernelWakelockStats();
6438
6439        if (m == null) {
6440            // Not crashing might make board bringup easier.
6441            Slog.w(TAG, "Couldn't get kernel wake lock stats");
6442            return;
6443        }
6444
6445        for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
6446            String name = ent.getKey();
6447            KernelWakelockStats kws = ent.getValue();
6448
6449            SamplingTimer kwlt = mKernelWakelockStats.get(name);
6450            if (kwlt == null) {
6451                kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
6452                        true /* track reported val */);
6453                mKernelWakelockStats.put(name, kwlt);
6454            }
6455            kwlt.updateCurrentReportedCount(kws.mCount);
6456            kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
6457            kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
6458        }
6459
6460        if (m.size() != mKernelWakelockStats.size()) {
6461            // Set timers to stale if they didn't appear in /proc/wakelocks this time.
6462            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
6463                SamplingTimer st = ent.getValue();
6464                if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
6465                    st.setStale();
6466                }
6467            }
6468        }
6469    }
6470
6471    static final int NET_UPDATE_MOBILE = 1<<0;
6472    static final int NET_UPDATE_WIFI = 1<<1;
6473    static final int NET_UPDATE_ALL = 0xffff;
6474
6475    private void updateNetworkActivityLocked(int which, long elapsedRealtimeMs) {
6476        if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
6477
6478        if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) {
6479            final NetworkStats snapshot;
6480            final NetworkStats last = mCurMobileSnapshot;
6481            try {
6482                snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
6483                        mMobileIfaces, NetworkStats.TAG_NONE, mLastMobileSnapshot);
6484            } catch (IOException e) {
6485                Log.wtf(TAG, "Failed to read mobile network stats", e);
6486                return;
6487            }
6488
6489            mCurMobileSnapshot = snapshot;
6490            mLastMobileSnapshot = last;
6491
6492            if (mOnBatteryInternal) {
6493                final NetworkStats delta = NetworkStats.subtract(snapshot, last,
6494                        null, null, mTmpNetworkStats);
6495                mTmpNetworkStats = delta;
6496
6497                long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked(
6498                        elapsedRealtimeMs);
6499                long totalPackets = delta.getTotalPackets();
6500
6501                final int size = delta.size();
6502                for (int i = 0; i < size; i++) {
6503                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
6504
6505                    if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
6506
6507                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
6508                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
6509                            entry.rxPackets);
6510                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
6511                            entry.txPackets);
6512
6513                    if (radioTime > 0) {
6514                        // Distribute total radio active time in to this app.
6515                        long appPackets = entry.rxPackets + entry.txPackets;
6516                        long appRadioTime = (radioTime*appPackets)/totalPackets;
6517                        u.noteMobileRadioActiveTimeLocked(appRadioTime);
6518                        // Remove this app from the totals, so that we don't lose any time
6519                        // due to rounding.
6520                        radioTime -= appRadioTime;
6521                        totalPackets -= appPackets;
6522                    }
6523
6524                    mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
6525                            entry.rxBytes);
6526                    mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
6527                            entry.txBytes);
6528                    mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
6529                            entry.rxPackets);
6530                    mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
6531                            entry.txPackets);
6532                }
6533
6534                if (radioTime > 0) {
6535                    // Whoops, there is some radio time we can't blame on an app!
6536                    mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
6537                    mMobileRadioActiveUnknownCount.addCountLocked(1);
6538                }
6539            }
6540        }
6541
6542        if ((which&NET_UPDATE_WIFI) != 0 && mWifiIfaces.length > 0) {
6543            final NetworkStats snapshot;
6544            final NetworkStats last = mCurWifiSnapshot;
6545            try {
6546                snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
6547                        mWifiIfaces, NetworkStats.TAG_NONE, mLastWifiSnapshot);
6548            } catch (IOException e) {
6549                Log.wtf(TAG, "Failed to read wifi network stats", e);
6550                return;
6551            }
6552
6553            mCurWifiSnapshot = snapshot;
6554            mLastWifiSnapshot = last;
6555
6556            if (mOnBatteryInternal) {
6557                final NetworkStats delta = NetworkStats.subtract(snapshot, last,
6558                        null, null, mTmpNetworkStats);
6559                mTmpNetworkStats = delta;
6560
6561                final int size = delta.size();
6562                for (int i = 0; i < size; i++) {
6563                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
6564
6565                    if (DEBUG) {
6566                        final NetworkStats.Entry cur = snapshot.getValues(i, null);
6567                        Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
6568                                + " tx=" + entry.txBytes + ", cur rx=" + cur.rxBytes
6569                                + " tx=" + cur.txBytes);
6570                    }
6571
6572                    if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
6573
6574                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
6575                    u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
6576                            entry.rxPackets);
6577                    u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
6578                            entry.txPackets);
6579
6580                    mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
6581                            entry.rxBytes);
6582                    mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
6583                            entry.txBytes);
6584                    mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
6585                            entry.rxPackets);
6586                    mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
6587                            entry.txPackets);
6588                }
6589            }
6590        }
6591    }
6592
6593    public long getAwakeTimeBattery() {
6594        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
6595    }
6596
6597    public long getAwakeTimePlugged() {
6598        return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
6599    }
6600
6601    @Override
6602    public long computeUptime(long curTime, int which) {
6603        switch (which) {
6604            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
6605            case STATS_CURRENT: return (curTime-mUptimeStart);
6606            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
6607        }
6608        return 0;
6609    }
6610
6611    @Override
6612    public long computeRealtime(long curTime, int which) {
6613        switch (which) {
6614            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
6615            case STATS_CURRENT: return (curTime-mRealtimeStart);
6616            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
6617        }
6618        return 0;
6619    }
6620
6621    @Override
6622    public long computeBatteryUptime(long curTime, int which) {
6623        return mOnBatteryTimeBase.computeUptime(curTime, which);
6624    }
6625
6626    @Override
6627    public long computeBatteryRealtime(long curTime, int which) {
6628        return mOnBatteryTimeBase.computeRealtime(curTime, which);
6629    }
6630
6631    @Override
6632    public long computeBatteryScreenOffUptime(long curTime, int which) {
6633        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
6634    }
6635
6636    @Override
6637    public long computeBatteryScreenOffRealtime(long curTime, int which) {
6638        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
6639    }
6640
6641    private long computeTimePerLevel(long[] steps, int numSteps) {
6642        // For now we'll do a simple average across all steps.
6643        if (numSteps <= 0) {
6644            return -1;
6645        }
6646        long total = 0;
6647        for (int i=0; i<numSteps; i++) {
6648            total += steps[i];
6649        }
6650        return total / numSteps;
6651        /*
6652        long[] buckets = new long[numSteps];
6653        int numBuckets = 0;
6654        int numToAverage = 4;
6655        int i = 0;
6656        while (i < numSteps) {
6657            long totalTime = 0;
6658            int num = 0;
6659            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
6660                totalTime += steps[i+j];
6661                num++;
6662            }
6663            buckets[numBuckets] = totalTime / num;
6664            numBuckets++;
6665            numToAverage *= 2;
6666            i += num;
6667        }
6668        if (numBuckets < 1) {
6669            return -1;
6670        }
6671        long averageTime = buckets[numBuckets-1];
6672        for (i=numBuckets-2; i>=0; i--) {
6673            averageTime = (averageTime + buckets[i]) / 2;
6674        }
6675        return averageTime;
6676        */
6677    }
6678
6679    @Override
6680    public long computeBatteryTimeRemaining(long curTime) {
6681        if (!mOnBattery) {
6682            return -1;
6683        }
6684        /* Simple implementation just looks at the average discharge per level across the
6685           entire sample period.
6686        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
6687        if (discharge < 2) {
6688            return -1;
6689        }
6690        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
6691        if (duration < 1000*1000) {
6692            return -1;
6693        }
6694        long usPerLevel = duration/discharge;
6695        return usPerLevel * mCurrentBatteryLevel;
6696        */
6697        if (mNumDischargeStepDurations < 1) {
6698            return -1;
6699        }
6700        long msPerLevel = computeTimePerLevel(mDischargeStepDurations, mNumDischargeStepDurations);
6701        if (msPerLevel <= 0) {
6702            return -1;
6703        }
6704        return (msPerLevel * mCurrentBatteryLevel) * 1000;
6705    }
6706
6707    public int getNumDischargeStepDurations() {
6708        return mNumDischargeStepDurations;
6709    }
6710
6711    public long[] getDischargeStepDurationsArray() {
6712        return mDischargeStepDurations;
6713    }
6714
6715    @Override
6716    public long computeChargeTimeRemaining(long curTime) {
6717        if (mOnBattery) {
6718            // Not yet working.
6719            return -1;
6720        }
6721        /* Broken
6722        int curLevel = mCurrentBatteryLevel;
6723        int plugLevel = mDischargePlugLevel;
6724        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
6725            return -1;
6726        }
6727        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
6728        if (duration < 1000*1000) {
6729            return -1;
6730        }
6731        long usPerLevel = duration/(curLevel-plugLevel);
6732        return usPerLevel * (100-curLevel);
6733        */
6734        if (mNumChargeStepDurations < 1) {
6735            return -1;
6736        }
6737        long msPerLevel = computeTimePerLevel(mChargeStepDurations, mNumChargeStepDurations);
6738        if (msPerLevel <= 0) {
6739            return -1;
6740        }
6741        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
6742    }
6743
6744    public int getNumChargeStepDurations() {
6745        return mNumChargeStepDurations;
6746    }
6747
6748    public long[] getChargeStepDurationsArray() {
6749        return mChargeStepDurations;
6750    }
6751
6752    long getBatteryUptimeLocked() {
6753        return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
6754    }
6755
6756    @Override
6757    public long getBatteryUptime(long curTime) {
6758        return mOnBatteryTimeBase.getUptime(curTime);
6759    }
6760
6761    @Override
6762    public long getBatteryRealtime(long curTime) {
6763        return mOnBatteryTimeBase.getRealtime(curTime);
6764    }
6765
6766    @Override
6767    public int getDischargeStartLevel() {
6768        synchronized(this) {
6769            return getDischargeStartLevelLocked();
6770        }
6771    }
6772
6773    public int getDischargeStartLevelLocked() {
6774            return mDischargeUnplugLevel;
6775    }
6776
6777    @Override
6778    public int getDischargeCurrentLevel() {
6779        synchronized(this) {
6780            return getDischargeCurrentLevelLocked();
6781        }
6782    }
6783
6784    public int getDischargeCurrentLevelLocked() {
6785        return mDischargeCurrentLevel;
6786    }
6787
6788    @Override
6789    public int getLowDischargeAmountSinceCharge() {
6790        synchronized(this) {
6791            int val = mLowDischargeAmountSinceCharge;
6792            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
6793                val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
6794            }
6795            return val;
6796        }
6797    }
6798
6799    @Override
6800    public int getHighDischargeAmountSinceCharge() {
6801        synchronized(this) {
6802            int val = mHighDischargeAmountSinceCharge;
6803            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
6804                val += mDischargeUnplugLevel-mDischargeCurrentLevel;
6805            }
6806            return val;
6807        }
6808    }
6809
6810    @Override
6811    public int getDischargeAmount(int which) {
6812        int dischargeAmount = which == STATS_SINCE_CHARGED
6813                ? getHighDischargeAmountSinceCharge()
6814                : (getDischargeStartLevel() - getDischargeCurrentLevel());
6815        if (dischargeAmount < 0) {
6816            dischargeAmount = 0;
6817        }
6818        return dischargeAmount;
6819    }
6820
6821    public int getDischargeAmountScreenOn() {
6822        synchronized(this) {
6823            int val = mDischargeAmountScreenOn;
6824            if (mOnBattery && mScreenState == Display.STATE_ON
6825                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
6826                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
6827            }
6828            return val;
6829        }
6830    }
6831
6832    public int getDischargeAmountScreenOnSinceCharge() {
6833        synchronized(this) {
6834            int val = mDischargeAmountScreenOnSinceCharge;
6835            if (mOnBattery && mScreenState == Display.STATE_ON
6836                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
6837                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
6838            }
6839            return val;
6840        }
6841    }
6842
6843    public int getDischargeAmountScreenOff() {
6844        synchronized(this) {
6845            int val = mDischargeAmountScreenOff;
6846            if (mOnBattery && mScreenState != Display.STATE_ON
6847                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
6848                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
6849            }
6850            return val;
6851        }
6852    }
6853
6854    public int getDischargeAmountScreenOffSinceCharge() {
6855        synchronized(this) {
6856            int val = mDischargeAmountScreenOffSinceCharge;
6857            if (mOnBattery && mScreenState != Display.STATE_ON
6858                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
6859                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
6860            }
6861            return val;
6862        }
6863    }
6864
6865    @Override
6866    public int getCpuSpeedSteps() {
6867        return sNumSpeedSteps;
6868    }
6869
6870    /**
6871     * Retrieve the statistics object for a particular uid, creating if needed.
6872     */
6873    public Uid getUidStatsLocked(int uid) {
6874        Uid u = mUidStats.get(uid);
6875        if (u == null) {
6876            u = new Uid(uid);
6877            mUidStats.put(uid, u);
6878        }
6879        return u;
6880    }
6881
6882    /**
6883     * Remove the statistics object for a particular uid.
6884     */
6885    public void removeUidStatsLocked(int uid) {
6886        mUidStats.remove(uid);
6887    }
6888
6889    /**
6890     * Retrieve the statistics object for a particular process, creating
6891     * if needed.
6892     */
6893    public Uid.Proc getProcessStatsLocked(int uid, String name) {
6894        uid = mapUid(uid);
6895        Uid u = getUidStatsLocked(uid);
6896        return u.getProcessStatsLocked(name);
6897    }
6898
6899    /**
6900     * Retrieve the statistics object for a particular process, creating
6901     * if needed.
6902     */
6903    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
6904        uid = mapUid(uid);
6905        Uid u = getUidStatsLocked(uid);
6906        return u.getPackageStatsLocked(pkg);
6907    }
6908
6909    /**
6910     * Retrieve the statistics object for a particular service, creating
6911     * if needed.
6912     */
6913    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
6914        uid = mapUid(uid);
6915        Uid u = getUidStatsLocked(uid);
6916        return u.getServiceStatsLocked(pkg, name);
6917    }
6918
6919    /**
6920     * Massage data to distribute any reasonable work down to more specific
6921     * owners.  Must only be called on a dead BatteryStats object!
6922     */
6923    public void distributeWorkLocked(int which) {
6924        // Aggregate all CPU time associated with WIFI.
6925        Uid wifiUid = mUidStats.get(Process.WIFI_UID);
6926        if (wifiUid != null) {
6927            long uSecTime = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
6928            for (int ip=wifiUid.mProcessStats.size()-1; ip>=0; ip--) {
6929                Uid.Proc proc = wifiUid.mProcessStats.valueAt(ip);
6930                long totalRunningTime = getGlobalWifiRunningTime(uSecTime, which);
6931                for (int i=0; i<mUidStats.size(); i++) {
6932                    Uid uid = mUidStats.valueAt(i);
6933                    if (uid.mUid != Process.WIFI_UID) {
6934                        long uidRunningTime = uid.getWifiRunningTime(uSecTime, which);
6935                        if (uidRunningTime > 0) {
6936                            Uid.Proc uidProc = uid.getProcessStatsLocked("*wifi*");
6937                            long time = proc.getUserTime(which);
6938                            time = (time*uidRunningTime)/totalRunningTime;
6939                            uidProc.mUserTime += time;
6940                            proc.mUserTime -= time;
6941                            time = proc.getSystemTime(which);
6942                            time = (time*uidRunningTime)/totalRunningTime;
6943                            uidProc.mSystemTime += time;
6944                            proc.mSystemTime -= time;
6945                            time = proc.getForegroundTime(which);
6946                            time = (time*uidRunningTime)/totalRunningTime;
6947                            uidProc.mForegroundTime += time;
6948                            proc.mForegroundTime -= time;
6949                            for (int sb=0; sb<proc.mSpeedBins.length; sb++) {
6950                                SamplingCounter sc = proc.mSpeedBins[sb];
6951                                if (sc != null) {
6952                                    time = sc.getCountLocked(which);
6953                                    time = (time*uidRunningTime)/totalRunningTime;
6954                                    SamplingCounter uidSc = uidProc.mSpeedBins[sb];
6955                                    if (uidSc == null) {
6956                                        uidSc = new SamplingCounter(mOnBatteryTimeBase);
6957                                        uidProc.mSpeedBins[sb] = uidSc;
6958                                    }
6959                                    uidSc.mCount.addAndGet((int)time);
6960                                    sc.mCount.addAndGet((int)-time);
6961                                }
6962                            }
6963                            totalRunningTime -= uidRunningTime;
6964                        }
6965                    }
6966                }
6967            }
6968        }
6969    }
6970
6971    public void shutdownLocked() {
6972        writeSyncLocked();
6973        mShuttingDown = true;
6974    }
6975
6976    Parcel mPendingWrite = null;
6977    final ReentrantLock mWriteLock = new ReentrantLock();
6978
6979    public void writeAsyncLocked() {
6980        writeLocked(false);
6981    }
6982
6983    public void writeSyncLocked() {
6984        writeLocked(true);
6985    }
6986
6987    void writeLocked(boolean sync) {
6988        if (mFile == null) {
6989            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
6990            return;
6991        }
6992
6993        if (mShuttingDown) {
6994            return;
6995        }
6996
6997        Parcel out = Parcel.obtain();
6998        writeSummaryToParcel(out);
6999        mLastWriteTime = SystemClock.elapsedRealtime();
7000
7001        if (mPendingWrite != null) {
7002            mPendingWrite.recycle();
7003        }
7004        mPendingWrite = out;
7005
7006        if (sync) {
7007            commitPendingDataToDisk();
7008        } else {
7009            Thread thr = new Thread("BatteryStats-Write") {
7010                @Override
7011                public void run() {
7012                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
7013                    commitPendingDataToDisk();
7014                }
7015            };
7016            thr.start();
7017        }
7018    }
7019
7020    public void commitPendingDataToDisk() {
7021        final Parcel next;
7022        synchronized (this) {
7023            next = mPendingWrite;
7024            mPendingWrite = null;
7025            if (next == null) {
7026                return;
7027            }
7028
7029            mWriteLock.lock();
7030        }
7031
7032        try {
7033            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
7034            stream.write(next.marshall());
7035            stream.flush();
7036            FileUtils.sync(stream);
7037            stream.close();
7038            mFile.commit();
7039        } catch (IOException e) {
7040            Slog.w("BatteryStats", "Error writing battery statistics", e);
7041            mFile.rollback();
7042        } finally {
7043            next.recycle();
7044            mWriteLock.unlock();
7045        }
7046    }
7047
7048    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
7049        int pos = 0;
7050        int avail = stream.available();
7051        byte[] data = new byte[avail];
7052        while (true) {
7053            int amt = stream.read(data, pos, data.length-pos);
7054            //Log.i("foo", "Read " + amt + " bytes at " + pos
7055            //        + " of avail " + data.length);
7056            if (amt <= 0) {
7057                //Log.i("foo", "**** FINISHED READING: pos=" + pos
7058                //        + " len=" + data.length);
7059                return data;
7060            }
7061            pos += amt;
7062            avail = stream.available();
7063            if (avail > data.length-pos) {
7064                byte[] newData = new byte[pos+avail];
7065                System.arraycopy(data, 0, newData, 0, pos);
7066                data = newData;
7067            }
7068        }
7069    }
7070
7071    public void readLocked() {
7072        if (mFile == null) {
7073            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
7074            return;
7075        }
7076
7077        mUidStats.clear();
7078
7079        try {
7080            File file = mFile.chooseForRead();
7081            if (!file.exists()) {
7082                return;
7083            }
7084            FileInputStream stream = new FileInputStream(file);
7085
7086            byte[] raw = readFully(stream);
7087            Parcel in = Parcel.obtain();
7088            in.unmarshall(raw, 0, raw.length);
7089            in.setDataPosition(0);
7090            stream.close();
7091
7092            readSummaryFromParcel(in);
7093        } catch(Exception e) {
7094            Slog.e("BatteryStats", "Error reading battery statistics", e);
7095        }
7096
7097        if (mHistoryBuffer.dataPosition() > 0) {
7098            mRecordingHistory = true;
7099            final long elapsedRealtime = SystemClock.elapsedRealtime();
7100            final long uptime = SystemClock.uptimeMillis();
7101            if (USE_OLD_HISTORY) {
7102                addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
7103            }
7104            addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
7105            startRecordingHistory(elapsedRealtime, uptime, false);
7106        }
7107    }
7108
7109    public int describeContents() {
7110        return 0;
7111    }
7112
7113    void readHistory(Parcel in, boolean andOldHistory) {
7114        final long historyBaseTime = in.readLong();
7115
7116        mHistoryBuffer.setDataSize(0);
7117        mHistoryBuffer.setDataPosition(0);
7118        mHistoryTagPool.clear();
7119        mNextHistoryTagIdx = 0;
7120        mNumHistoryTagChars = 0;
7121
7122        int numTags = in.readInt();
7123        for (int i=0; i<numTags; i++) {
7124            int idx = in.readInt();
7125            String str = in.readString();
7126            int uid = in.readInt();
7127            HistoryTag tag = new HistoryTag();
7128            tag.string = str;
7129            tag.uid = uid;
7130            tag.poolIdx = idx;
7131            mHistoryTagPool.put(tag, idx);
7132            if (idx >= mNextHistoryTagIdx) {
7133                mNextHistoryTagIdx = idx+1;
7134            }
7135            mNumHistoryTagChars += tag.string.length() + 1;
7136        }
7137
7138        int bufSize = in.readInt();
7139        int curPos = in.dataPosition();
7140        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
7141            Slog.w(TAG, "File corrupt: history data buffer too large " + bufSize);
7142        } else if ((bufSize&~3) != bufSize) {
7143            Slog.w(TAG, "File corrupt: history data buffer not aligned " + bufSize);
7144        } else {
7145            if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
7146                    + " bytes at " + curPos);
7147            mHistoryBuffer.appendFrom(in, curPos, bufSize);
7148            in.setDataPosition(curPos + bufSize);
7149        }
7150
7151        if (andOldHistory) {
7152            readOldHistory(in);
7153        }
7154
7155        if (DEBUG_HISTORY) {
7156            StringBuilder sb = new StringBuilder(128);
7157            sb.append("****************** OLD mHistoryBaseTime: ");
7158            TimeUtils.formatDuration(mHistoryBaseTime, sb);
7159            Slog.i(TAG, sb.toString());
7160        }
7161        mHistoryBaseTime = historyBaseTime;
7162        if (DEBUG_HISTORY) {
7163            StringBuilder sb = new StringBuilder(128);
7164            sb.append("****************** NEW mHistoryBaseTime: ");
7165            TimeUtils.formatDuration(mHistoryBaseTime, sb);
7166            Slog.i(TAG, sb.toString());
7167        }
7168
7169        // We are just arbitrarily going to insert 1 minute from the sample of
7170        // the last run until samples in this run.
7171        if (mHistoryBaseTime > 0) {
7172            long oldnow = SystemClock.elapsedRealtime();
7173            mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
7174            if (DEBUG_HISTORY) {
7175                StringBuilder sb = new StringBuilder(128);
7176                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
7177                TimeUtils.formatDuration(mHistoryBaseTime, sb);
7178                Slog.i(TAG, sb.toString());
7179            }
7180        }
7181    }
7182
7183    void readOldHistory(Parcel in) {
7184        if (!USE_OLD_HISTORY) {
7185            return;
7186        }
7187        mHistory = mHistoryEnd = mHistoryCache = null;
7188        long time;
7189        while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
7190            HistoryItem rec = new HistoryItem(time, in);
7191            addHistoryRecordLocked(rec);
7192        }
7193    }
7194
7195    void writeHistory(Parcel out, boolean andOldHistory) {
7196        if (DEBUG_HISTORY) {
7197            StringBuilder sb = new StringBuilder(128);
7198            sb.append("****************** WRITING mHistoryBaseTime: ");
7199            TimeUtils.formatDuration(mHistoryBaseTime, sb);
7200            sb.append(" mLastHistoryElapsedRealtime: ");
7201            TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
7202            Slog.i(TAG, sb.toString());
7203        }
7204        out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
7205        out.writeInt(mHistoryTagPool.size());
7206        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
7207            HistoryTag tag = ent.getKey();
7208            out.writeInt(ent.getValue());
7209            out.writeString(tag.string);
7210            out.writeInt(tag.uid);
7211        }
7212        out.writeInt(mHistoryBuffer.dataSize());
7213        if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
7214                + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
7215        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
7216
7217        if (andOldHistory) {
7218            writeOldHistory(out);
7219        }
7220    }
7221
7222    void writeOldHistory(Parcel out) {
7223        if (!USE_OLD_HISTORY) {
7224            return;
7225        }
7226        HistoryItem rec = mHistory;
7227        while (rec != null) {
7228            if (rec.time >= 0) rec.writeToParcel(out, 0);
7229            rec = rec.next;
7230        }
7231        out.writeLong(-1);
7232    }
7233
7234    private void readSummaryFromParcel(Parcel in) {
7235        final int version = in.readInt();
7236        if (version != VERSION) {
7237            Slog.w("BatteryStats", "readFromParcel: version got " + version
7238                + ", expected " + VERSION + "; erasing old stats");
7239            return;
7240        }
7241
7242        readHistory(in, true);
7243
7244        mStartCount = in.readInt();
7245        mUptime = in.readLong();
7246        mRealtime = in.readLong();
7247        mStartClockTime = in.readLong();
7248        mOnBatteryTimeBase.readSummaryFromParcel(in);
7249        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
7250        mDischargeUnplugLevel = in.readInt();
7251        mDischargePlugLevel = in.readInt();
7252        mDischargeCurrentLevel = in.readInt();
7253        mCurrentBatteryLevel = in.readInt();
7254        mLowDischargeAmountSinceCharge = in.readInt();
7255        mHighDischargeAmountSinceCharge = in.readInt();
7256        mDischargeAmountScreenOnSinceCharge = in.readInt();
7257        mDischargeAmountScreenOffSinceCharge = in.readInt();
7258        mNumDischargeStepDurations = in.readInt();
7259        in.readLongArray(mDischargeStepDurations);
7260        mNumChargeStepDurations = in.readInt();
7261        in.readLongArray(mChargeStepDurations);
7262
7263        mStartCount++;
7264
7265        mScreenState = Display.STATE_UNKNOWN;
7266        mScreenOnTimer.readSummaryFromParcelLocked(in);
7267        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
7268            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
7269        }
7270        mInteractive = false;
7271        mInteractiveTimer.readSummaryFromParcelLocked(in);
7272        mPhoneOn = false;
7273        mLowPowerModeEnabledTimer.readSummaryFromParcelLocked(in);
7274        mPhoneOnTimer.readSummaryFromParcelLocked(in);
7275        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
7276            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
7277        }
7278        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
7279        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
7280            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
7281        }
7282        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7283            mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
7284            mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
7285        }
7286        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
7287        mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
7288        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
7289        mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
7290        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
7291        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
7292        mWifiOn = false;
7293        mWifiOnTimer.readSummaryFromParcelLocked(in);
7294        mGlobalWifiRunning = false;
7295        mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
7296        for (int i=0; i<NUM_WIFI_STATES; i++) {
7297            mWifiStateTimer[i].readSummaryFromParcelLocked(in);
7298        }
7299        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
7300            mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
7301        }
7302        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7303            mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
7304        }
7305        mBluetoothOn = false;
7306        mBluetoothOnTimer.readSummaryFromParcelLocked(in);
7307        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
7308            mBluetoothStateTimer[i].readSummaryFromParcelLocked(in);
7309        }
7310        mFlashlightOn = false;
7311        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
7312
7313        int NKW = in.readInt();
7314        if (NKW > 10000) {
7315            Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW);
7316            return;
7317        }
7318        for (int ikw = 0; ikw < NKW; ikw++) {
7319            if (in.readInt() != 0) {
7320                String kwltName = in.readString();
7321                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
7322            }
7323        }
7324
7325        int NWR = in.readInt();
7326        if (NWR > 10000) {
7327            Slog.w(TAG, "File corrupt: too many wakeup reasons " + NWR);
7328            return;
7329        }
7330        for (int iwr = 0; iwr < NWR; iwr++) {
7331            if (in.readInt() != 0) {
7332                String reasonName = in.readString();
7333                getWakeupReasonCounterLocked(reasonName).readSummaryFromParcelLocked(in);
7334            }
7335        }
7336
7337        sNumSpeedSteps = in.readInt();
7338        if (sNumSpeedSteps < 0 || sNumSpeedSteps > 100) {
7339            throw new BadParcelableException("Bad speed steps in data: " + sNumSpeedSteps);
7340        }
7341
7342        final int NU = in.readInt();
7343        if (NU > 10000) {
7344            Slog.w(TAG, "File corrupt: too many uids " + NU);
7345            return;
7346        }
7347        for (int iu = 0; iu < NU; iu++) {
7348            int uid = in.readInt();
7349            Uid u = new Uid(uid);
7350            mUidStats.put(uid, u);
7351
7352            u.mWifiRunning = false;
7353            if (in.readInt() != 0) {
7354                u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
7355            }
7356            u.mFullWifiLockOut = false;
7357            if (in.readInt() != 0) {
7358                u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
7359            }
7360            u.mWifiScanStarted = false;
7361            if (in.readInt() != 0) {
7362                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
7363            }
7364            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
7365            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7366                if (in.readInt() != 0) {
7367                    u.makeWifiBatchedScanBin(i, null);
7368                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
7369                }
7370            }
7371            u.mWifiMulticastEnabled = false;
7372            if (in.readInt() != 0) {
7373                u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
7374            }
7375            u.mAudioTurnedOn = false;
7376            if (in.readInt() != 0) {
7377                u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
7378            }
7379            u.mVideoTurnedOn = false;
7380            if (in.readInt() != 0) {
7381                u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
7382            }
7383            if (in.readInt() != 0) {
7384                u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
7385            }
7386            u.mProcessState = Uid.PROCESS_STATE_NONE;
7387            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
7388                if (in.readInt() != 0) {
7389                    u.makeProcessState(i, null);
7390                    u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
7391                }
7392            }
7393            if (in.readInt() != 0) {
7394                u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
7395            }
7396
7397            if (in.readInt() != 0) {
7398                if (u.mUserActivityCounters == null) {
7399                    u.initUserActivityLocked();
7400                }
7401                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
7402                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
7403                }
7404            }
7405
7406            if (in.readInt() != 0) {
7407                if (u.mNetworkByteActivityCounters == null) {
7408                    u.initNetworkActivityLocked();
7409                }
7410                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7411                    u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
7412                    u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
7413                }
7414                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
7415                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
7416            }
7417
7418            int NW = in.readInt();
7419            if (NW > 100) {
7420                Slog.w(TAG, "File corrupt: too many wake locks " + NW);
7421                return;
7422            }
7423            for (int iw = 0; iw < NW; iw++) {
7424                String wlName = in.readString();
7425                if (in.readInt() != 0) {
7426                    u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
7427                }
7428                if (in.readInt() != 0) {
7429                    u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
7430                }
7431                if (in.readInt() != 0) {
7432                    u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
7433                }
7434            }
7435
7436            int NP = in.readInt();
7437            if (NP > 1000) {
7438                Slog.w(TAG, "File corrupt: too many sensors " + NP);
7439                return;
7440            }
7441            for (int is = 0; is < NP; is++) {
7442                int seNumber = in.readInt();
7443                if (in.readInt() != 0) {
7444                    u.getSensorTimerLocked(seNumber, true)
7445                            .readSummaryFromParcelLocked(in);
7446                }
7447            }
7448
7449            NP = in.readInt();
7450            if (NP > 1000) {
7451                Slog.w(TAG, "File corrupt: too many processes " + NP);
7452                return;
7453            }
7454            for (int ip = 0; ip < NP; ip++) {
7455                String procName = in.readString();
7456                Uid.Proc p = u.getProcessStatsLocked(procName);
7457                p.mUserTime = p.mLoadedUserTime = in.readLong();
7458                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
7459                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
7460                p.mStarts = p.mLoadedStarts = in.readInt();
7461                int NSB = in.readInt();
7462                if (NSB > 100) {
7463                    Slog.w(TAG, "File corrupt: too many speed bins " + NSB);
7464                    return;
7465                }
7466                p.mSpeedBins = new SamplingCounter[NSB];
7467                for (int i=0; i<NSB; i++) {
7468                    if (in.readInt() != 0) {
7469                        p.mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase);
7470                        p.mSpeedBins[i].readSummaryFromParcelLocked(in);
7471                    }
7472                }
7473                if (!p.readExcessivePowerFromParcelLocked(in)) {
7474                    return;
7475                }
7476            }
7477
7478            NP = in.readInt();
7479            if (NP > 10000) {
7480                Slog.w(TAG, "File corrupt: too many packages " + NP);
7481                return;
7482            }
7483            for (int ip = 0; ip < NP; ip++) {
7484                String pkgName = in.readString();
7485                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
7486                p.mWakeups = p.mLoadedWakeups = in.readInt();
7487                final int NS = in.readInt();
7488                if (NS > 1000) {
7489                    Slog.w(TAG, "File corrupt: too many services " + NS);
7490                    return;
7491                }
7492                for (int is = 0; is < NS; is++) {
7493                    String servName = in.readString();
7494                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
7495                    s.mStartTime = s.mLoadedStartTime = in.readLong();
7496                    s.mStarts = s.mLoadedStarts = in.readInt();
7497                    s.mLaunches = s.mLoadedLaunches = in.readInt();
7498                }
7499            }
7500        }
7501    }
7502
7503    /**
7504     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
7505     * disk.  This format does not allow a lossless round-trip.
7506     *
7507     * @param out the Parcel to be written to.
7508     */
7509    public void writeSummaryToParcel(Parcel out) {
7510        pullPendingStateUpdatesLocked();
7511
7512        final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
7513        final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
7514
7515        out.writeInt(VERSION);
7516
7517        writeHistory(out, true);
7518
7519        out.writeInt(mStartCount);
7520        out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
7521        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
7522        out.writeLong(mStartClockTime);
7523        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
7524        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
7525        out.writeInt(mDischargeUnplugLevel);
7526        out.writeInt(mDischargePlugLevel);
7527        out.writeInt(mDischargeCurrentLevel);
7528        out.writeInt(mCurrentBatteryLevel);
7529        out.writeInt(getLowDischargeAmountSinceCharge());
7530        out.writeInt(getHighDischargeAmountSinceCharge());
7531        out.writeInt(getDischargeAmountScreenOnSinceCharge());
7532        out.writeInt(getDischargeAmountScreenOffSinceCharge());
7533        out.writeInt(mNumDischargeStepDurations);
7534        out.writeLongArray(mDischargeStepDurations);
7535        out.writeInt(mNumChargeStepDurations);
7536        out.writeLongArray(mChargeStepDurations);
7537
7538        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7539        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
7540            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7541        }
7542        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7543        mLowPowerModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7544        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7545        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
7546            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7547        }
7548        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7549        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
7550            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7551        }
7552        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7553            mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
7554            mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
7555        }
7556        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7557        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7558        mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
7559        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
7560        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
7561        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7562        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7563        for (int i=0; i<NUM_WIFI_STATES; i++) {
7564            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7565        }
7566        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
7567            mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7568        }
7569        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7570            mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7571        }
7572        mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7573        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
7574            mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7575        }
7576        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7577
7578        out.writeInt(mKernelWakelockStats.size());
7579        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
7580            Timer kwlt = ent.getValue();
7581            if (kwlt != null) {
7582                out.writeInt(1);
7583                out.writeString(ent.getKey());
7584                kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7585            } else {
7586                out.writeInt(0);
7587            }
7588        }
7589
7590        out.writeInt(mWakeupReasonStats.size());
7591        for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) {
7592            LongSamplingCounter counter = ent.getValue();
7593            if (counter != null) {
7594                out.writeInt(1);
7595                out.writeString(ent.getKey());
7596                counter.writeSummaryFromParcelLocked(out);
7597            } else {
7598                out.writeInt(0);
7599            }
7600        }
7601
7602        out.writeInt(sNumSpeedSteps);
7603        final int NU = mUidStats.size();
7604        out.writeInt(NU);
7605        for (int iu = 0; iu < NU; iu++) {
7606            out.writeInt(mUidStats.keyAt(iu));
7607            Uid u = mUidStats.valueAt(iu);
7608
7609            if (u.mWifiRunningTimer != null) {
7610                out.writeInt(1);
7611                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7612            } else {
7613                out.writeInt(0);
7614            }
7615            if (u.mFullWifiLockTimer != null) {
7616                out.writeInt(1);
7617                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7618            } else {
7619                out.writeInt(0);
7620            }
7621            if (u.mWifiScanTimer != null) {
7622                out.writeInt(1);
7623                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7624            } else {
7625                out.writeInt(0);
7626            }
7627            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
7628                if (u.mWifiBatchedScanTimer[i] != null) {
7629                    out.writeInt(1);
7630                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7631                } else {
7632                    out.writeInt(0);
7633                }
7634            }
7635            if (u.mWifiMulticastTimer != null) {
7636                out.writeInt(1);
7637                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7638            } else {
7639                out.writeInt(0);
7640            }
7641            if (u.mAudioTurnedOnTimer != null) {
7642                out.writeInt(1);
7643                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7644            } else {
7645                out.writeInt(0);
7646            }
7647            if (u.mVideoTurnedOnTimer != null) {
7648                out.writeInt(1);
7649                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7650            } else {
7651                out.writeInt(0);
7652            }
7653            if (u.mForegroundActivityTimer != null) {
7654                out.writeInt(1);
7655                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7656            } else {
7657                out.writeInt(0);
7658            }
7659            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
7660                if (u.mProcessStateTimer[i] != null) {
7661                    out.writeInt(1);
7662                    u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7663                } else {
7664                    out.writeInt(0);
7665                }
7666            }
7667            if (u.mVibratorOnTimer != null) {
7668                out.writeInt(1);
7669                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7670            } else {
7671                out.writeInt(0);
7672            }
7673
7674            if (u.mUserActivityCounters == null) {
7675                out.writeInt(0);
7676            } else {
7677                out.writeInt(1);
7678                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
7679                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
7680                }
7681            }
7682
7683            if (u.mNetworkByteActivityCounters == null) {
7684                out.writeInt(0);
7685            } else {
7686                out.writeInt(1);
7687                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7688                    u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
7689                    u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
7690                }
7691                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
7692                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
7693            }
7694
7695            int NW = u.mWakelockStats.size();
7696            out.writeInt(NW);
7697            for (int iw=0; iw<NW; iw++) {
7698                out.writeString(u.mWakelockStats.keyAt(iw));
7699                Uid.Wakelock wl = u.mWakelockStats.valueAt(iw);
7700                if (wl.mTimerFull != null) {
7701                    out.writeInt(1);
7702                    wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7703                } else {
7704                    out.writeInt(0);
7705                }
7706                if (wl.mTimerPartial != null) {
7707                    out.writeInt(1);
7708                    wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7709                } else {
7710                    out.writeInt(0);
7711                }
7712                if (wl.mTimerWindow != null) {
7713                    out.writeInt(1);
7714                    wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7715                } else {
7716                    out.writeInt(0);
7717                }
7718            }
7719
7720            int NSE = u.mSensorStats.size();
7721            out.writeInt(NSE);
7722            for (int ise=0; ise<NSE; ise++) {
7723                out.writeInt(u.mSensorStats.keyAt(ise));
7724                Uid.Sensor se = u.mSensorStats.valueAt(ise);
7725                if (se.mTimer != null) {
7726                    out.writeInt(1);
7727                    se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
7728                } else {
7729                    out.writeInt(0);
7730                }
7731            }
7732
7733            int NP = u.mProcessStats.size();
7734            out.writeInt(NP);
7735            for (int ip=0; ip<NP; ip++) {
7736                out.writeString(u.mProcessStats.keyAt(ip));
7737                Uid.Proc ps = u.mProcessStats.valueAt(ip);
7738                out.writeLong(ps.mUserTime);
7739                out.writeLong(ps.mSystemTime);
7740                out.writeLong(ps.mForegroundTime);
7741                out.writeInt(ps.mStarts);
7742                final int N = ps.mSpeedBins.length;
7743                out.writeInt(N);
7744                for (int i=0; i<N; i++) {
7745                    if (ps.mSpeedBins[i] != null) {
7746                        out.writeInt(1);
7747                        ps.mSpeedBins[i].writeSummaryFromParcelLocked(out);
7748                    } else {
7749                        out.writeInt(0);
7750                    }
7751                }
7752                ps.writeExcessivePowerToParcelLocked(out);
7753            }
7754
7755            NP = u.mPackageStats.size();
7756            out.writeInt(NP);
7757            if (NP > 0) {
7758                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
7759                    : u.mPackageStats.entrySet()) {
7760                    out.writeString(ent.getKey());
7761                    Uid.Pkg ps = ent.getValue();
7762                    out.writeInt(ps.mWakeups);
7763                    final int NS = ps.mServiceStats.size();
7764                    out.writeInt(NS);
7765                    if (NS > 0) {
7766                        for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
7767                                : ps.mServiceStats.entrySet()) {
7768                            out.writeString(sent.getKey());
7769                            BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
7770                            long time = ss.getStartTimeToNowLocked(
7771                                    mOnBatteryTimeBase.getUptime(NOW_SYS));
7772                            out.writeLong(time);
7773                            out.writeInt(ss.mStarts);
7774                            out.writeInt(ss.mLaunches);
7775                        }
7776                    }
7777                }
7778            }
7779        }
7780    }
7781
7782    public void readFromParcel(Parcel in) {
7783        readFromParcelLocked(in);
7784    }
7785
7786    void readFromParcelLocked(Parcel in) {
7787        int magic = in.readInt();
7788        if (magic != MAGIC) {
7789            throw new ParcelFormatException("Bad magic number");
7790        }
7791
7792        readHistory(in, false);
7793
7794        mStartCount = in.readInt();
7795        mStartClockTime = in.readLong();
7796        mUptime = in.readLong();
7797        mUptimeStart = in.readLong();
7798        mRealtime = in.readLong();
7799        mRealtimeStart = in.readLong();
7800        mOnBattery = in.readInt() != 0;
7801        mOnBatteryInternal = false; // we are no longer really running.
7802        mOnBatteryTimeBase.readFromParcel(in);
7803        mOnBatteryScreenOffTimeBase.readFromParcel(in);
7804
7805        mScreenState = Display.STATE_UNKNOWN;
7806        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
7807        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
7808            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
7809                    in);
7810        }
7811        mInteractive = false;
7812        mInteractiveTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
7813        mPhoneOn = false;
7814        mLowPowerModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
7815        mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
7816        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
7817            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
7818                    null, mOnBatteryTimeBase, in);
7819        }
7820        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase, in);
7821        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
7822            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
7823                    null, mOnBatteryTimeBase, in);
7824        }
7825        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7826            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
7827            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
7828        }
7829        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
7830        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in);
7831        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase,
7832                in);
7833        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
7834        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
7835        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
7836        mWifiOn = false;
7837        mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase, in);
7838        mGlobalWifiRunning = false;
7839        mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase, in);
7840        for (int i=0; i<NUM_WIFI_STATES; i++) {
7841            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
7842                    null, mOnBatteryTimeBase, in);
7843        }
7844        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
7845            mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i,
7846                    null, mOnBatteryTimeBase, in);
7847        }
7848        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7849            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
7850                    null, mOnBatteryTimeBase, in);
7851        }
7852        mBluetoothOn = false;
7853        mBluetoothOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase, in);
7854        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
7855            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
7856                    null, mOnBatteryTimeBase, in);
7857        }
7858        mAudioOn = false;
7859        mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
7860        mVideoOn = false;
7861        mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
7862        mFlashlightOn = false;
7863        mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
7864        mDischargeUnplugLevel = in.readInt();
7865        mDischargePlugLevel = in.readInt();
7866        mDischargeCurrentLevel = in.readInt();
7867        mCurrentBatteryLevel = in.readInt();
7868        mLowDischargeAmountSinceCharge = in.readInt();
7869        mHighDischargeAmountSinceCharge = in.readInt();
7870        mDischargeAmountScreenOn = in.readInt();
7871        mDischargeAmountScreenOnSinceCharge = in.readInt();
7872        mDischargeAmountScreenOff = in.readInt();
7873        mDischargeAmountScreenOffSinceCharge = in.readInt();
7874        mNumDischargeStepDurations = in.readInt();
7875        in.readLongArray(mDischargeStepDurations);
7876        mNumChargeStepDurations = in.readInt();
7877        in.readLongArray(mChargeStepDurations);
7878        mLastWriteTime = in.readLong();
7879
7880        mBluetoothPingCount = in.readInt();
7881        mBluetoothPingStart = -1;
7882
7883        mKernelWakelockStats.clear();
7884        int NKW = in.readInt();
7885        for (int ikw = 0; ikw < NKW; ikw++) {
7886            if (in.readInt() != 0) {
7887                String wakelockName = in.readString();
7888                SamplingTimer kwlt = new SamplingTimer(mOnBatteryTimeBase, in);
7889                mKernelWakelockStats.put(wakelockName, kwlt);
7890            }
7891        }
7892
7893        mWakeupReasonStats.clear();
7894        int NWR = in.readInt();
7895        for (int iwr = 0; iwr < NWR; iwr++) {
7896            if (in.readInt() != 0) {
7897                String reasonName = in.readString();
7898                LongSamplingCounter counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase,
7899                        in);
7900                mWakeupReasonStats.put(reasonName, counter);
7901            }
7902        }
7903
7904        mPartialTimers.clear();
7905        mFullTimers.clear();
7906        mWindowTimers.clear();
7907        mWifiRunningTimers.clear();
7908        mFullWifiLockTimers.clear();
7909        mWifiScanTimers.clear();
7910        mWifiBatchedScanTimers.clear();
7911        mWifiMulticastTimers.clear();
7912
7913        sNumSpeedSteps = in.readInt();
7914
7915        int numUids = in.readInt();
7916        mUidStats.clear();
7917        for (int i = 0; i < numUids; i++) {
7918            int uid = in.readInt();
7919            Uid u = new Uid(uid);
7920            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
7921            mUidStats.append(uid, u);
7922        }
7923    }
7924
7925    public void writeToParcel(Parcel out, int flags) {
7926        writeToParcelLocked(out, true, flags);
7927    }
7928
7929    public void writeToParcelWithoutUids(Parcel out, int flags) {
7930        writeToParcelLocked(out, false, flags);
7931    }
7932
7933    @SuppressWarnings("unused")
7934    void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
7935        // Need to update with current kernel wake lock counts.
7936        pullPendingStateUpdatesLocked();
7937
7938        final long uSecUptime = SystemClock.uptimeMillis() * 1000;
7939        final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
7940        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
7941        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
7942
7943        out.writeInt(MAGIC);
7944
7945        writeHistory(out, false);
7946
7947        out.writeInt(mStartCount);
7948        out.writeLong(mStartClockTime);
7949        out.writeLong(mUptime);
7950        out.writeLong(mUptimeStart);
7951        out.writeLong(mRealtime);
7952        out.writeLong(mRealtimeStart);
7953        out.writeInt(mOnBattery ? 1 : 0);
7954        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
7955        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
7956
7957        mScreenOnTimer.writeToParcel(out, uSecRealtime);
7958        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
7959            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
7960        }
7961        mInteractiveTimer.writeToParcel(out, uSecRealtime);
7962        mLowPowerModeEnabledTimer.writeToParcel(out, uSecRealtime);
7963        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
7964        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
7965            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
7966        }
7967        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
7968        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
7969            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
7970        }
7971        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7972            mNetworkByteActivityCounters[i].writeToParcel(out);
7973            mNetworkPacketActivityCounters[i].writeToParcel(out);
7974        }
7975        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
7976        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
7977        mMobileRadioActiveAdjustedTime.writeToParcel(out);
7978        mMobileRadioActiveUnknownTime.writeToParcel(out);
7979        mMobileRadioActiveUnknownCount.writeToParcel(out);
7980        mWifiOnTimer.writeToParcel(out, uSecRealtime);
7981        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
7982        for (int i=0; i<NUM_WIFI_STATES; i++) {
7983            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
7984        }
7985        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
7986            mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
7987        }
7988        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7989            mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
7990        }
7991        mBluetoothOnTimer.writeToParcel(out, uSecRealtime);
7992        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
7993            mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime);
7994        }
7995        mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
7996        out.writeInt(mDischargeUnplugLevel);
7997        out.writeInt(mDischargePlugLevel);
7998        out.writeInt(mDischargeCurrentLevel);
7999        out.writeInt(mCurrentBatteryLevel);
8000        out.writeInt(mLowDischargeAmountSinceCharge);
8001        out.writeInt(mHighDischargeAmountSinceCharge);
8002        out.writeInt(mDischargeAmountScreenOn);
8003        out.writeInt(mDischargeAmountScreenOnSinceCharge);
8004        out.writeInt(mDischargeAmountScreenOff);
8005        out.writeInt(mDischargeAmountScreenOffSinceCharge);
8006        out.writeInt(mNumDischargeStepDurations);
8007        out.writeLongArray(mDischargeStepDurations);
8008        out.writeInt(mNumChargeStepDurations);
8009        out.writeLongArray(mChargeStepDurations);
8010        out.writeLong(mLastWriteTime);
8011
8012        out.writeInt(getBluetoothPingCount());
8013
8014        if (inclUids) {
8015            out.writeInt(mKernelWakelockStats.size());
8016            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
8017                SamplingTimer kwlt = ent.getValue();
8018                if (kwlt != null) {
8019                    out.writeInt(1);
8020                    out.writeString(ent.getKey());
8021                    kwlt.writeToParcel(out, uSecRealtime);
8022                } else {
8023                    out.writeInt(0);
8024                }
8025            }
8026            out.writeInt(mWakeupReasonStats.size());
8027            for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) {
8028                LongSamplingCounter counter = ent.getValue();
8029                if (counter != null) {
8030                    out.writeInt(1);
8031                    out.writeString(ent.getKey());
8032                    counter.writeToParcel(out);
8033                } else {
8034                    out.writeInt(0);
8035                }
8036            }
8037        } else {
8038            out.writeInt(0);
8039        }
8040
8041        out.writeInt(sNumSpeedSteps);
8042
8043        if (inclUids) {
8044            int size = mUidStats.size();
8045            out.writeInt(size);
8046            for (int i = 0; i < size; i++) {
8047                out.writeInt(mUidStats.keyAt(i));
8048                Uid uid = mUidStats.valueAt(i);
8049
8050                uid.writeToParcelLocked(out, uSecRealtime);
8051            }
8052        } else {
8053            out.writeInt(0);
8054        }
8055    }
8056
8057    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
8058        new Parcelable.Creator<BatteryStatsImpl>() {
8059        public BatteryStatsImpl createFromParcel(Parcel in) {
8060            return new BatteryStatsImpl(in);
8061        }
8062
8063        public BatteryStatsImpl[] newArray(int size) {
8064            return new BatteryStatsImpl[size];
8065        }
8066    };
8067
8068    public void prepareForDumpLocked() {
8069        // Need to retrieve current kernel wake lock stats before printing.
8070        pullPendingStateUpdatesLocked();
8071    }
8072
8073    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
8074        if (DEBUG) {
8075            pw.println("mOnBatteryTimeBase:");
8076            mOnBatteryTimeBase.dump(pw, "  ");
8077            pw.println("mOnBatteryScreenOffTimeBase:");
8078            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
8079            Printer pr = new PrintWriterPrinter(pw);
8080            pr.println("*** Screen timer:");
8081            mScreenOnTimer.logState(pr, "  ");
8082            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
8083                pr.println("*** Screen brightness #" + i + ":");
8084                mScreenBrightnessTimer[i].logState(pr, "  ");
8085            }
8086            pr.println("*** Interactive timer:");
8087            mInteractiveTimer.logState(pr, "  ");
8088            pr.println("*** Low power mode timer:");
8089            mLowPowerModeEnabledTimer.logState(pr, "  ");
8090            pr.println("*** Phone timer:");
8091            mPhoneOnTimer.logState(pr, "  ");
8092            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
8093                pr.println("*** Phone signal strength #" + i + ":");
8094                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
8095            }
8096            pr.println("*** Signal scanning :");
8097            mPhoneSignalScanningTimer.logState(pr, "  ");
8098            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
8099                pr.println("*** Data connection type #" + i + ":");
8100                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
8101            }
8102            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
8103            pr.println("*** Mobile network active timer:");
8104            mMobileRadioActiveTimer.logState(pr, "  ");
8105            pr.println("*** Mobile network active adjusted timer:");
8106            mMobileRadioActiveAdjustedTime.logState(pr, "  ");
8107            pr.println("*** Wifi timer:");
8108            mWifiOnTimer.logState(pr, "  ");
8109            pr.println("*** WifiRunning timer:");
8110            mGlobalWifiRunningTimer.logState(pr, "  ");
8111            for (int i=0; i<NUM_WIFI_STATES; i++) {
8112                pr.println("*** Wifi state #" + i + ":");
8113                mWifiStateTimer[i].logState(pr, "  ");
8114            }
8115            for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
8116                pr.println("*** Wifi suppl state #" + i + ":");
8117                mWifiSupplStateTimer[i].logState(pr, "  ");
8118            }
8119            for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
8120                pr.println("*** Wifi signal strength #" + i + ":");
8121                mWifiSignalStrengthsTimer[i].logState(pr, "  ");
8122            }
8123            pr.println("*** Bluetooth timer:");
8124            mBluetoothOnTimer.logState(pr, "  ");
8125            for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
8126                pr.println("*** Bluetooth active type #" + i + ":");
8127                mBluetoothStateTimer[i].logState(pr, "  ");
8128            }
8129            pr.println("*** Flashlight timer:");
8130            mFlashlightOnTimer.logState(pr, "  ");
8131        }
8132        super.dumpLocked(context, pw, flags, reqUid, histStart);
8133    }
8134}
8135