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