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