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