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