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