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