BatteryStatsImpl.java revision fbabe7dd6a25f1ed1228ea65a2305f298427a99b
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    boolean ensureStartClockTime(final long currentTime) {
2564        final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
2565        if (currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR)) {
2566            // If the start clock time has changed by more than a year, then presumably
2567            // the previous time was completely bogus.  So we are going to figure out a
2568            // new time based on how much time has elapsed since we started counting.
2569            mStartClockTime = currentTime - (SystemClock.elapsedRealtime()-(mRealtimeStart/1000));
2570            return true;
2571        }
2572        return false;
2573    }
2574
2575    public void noteCurrentTimeChangedLocked() {
2576        final long currentTime = System.currentTimeMillis();
2577        final long elapsedRealtime = SystemClock.elapsedRealtime();
2578        final long uptime = SystemClock.uptimeMillis();
2579        recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
2580        ensureStartClockTime(currentTime);
2581    }
2582
2583    public void noteProcessStartLocked(String name, int uid) {
2584        uid = mapUid(uid);
2585        if (isOnBattery()) {
2586            Uid u = getUidStatsLocked(uid);
2587            u.getProcessStatsLocked(name).incStartsLocked();
2588        }
2589        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
2590            return;
2591        }
2592        if (!mRecordAllHistory) {
2593            return;
2594        }
2595        final long elapsedRealtime = SystemClock.elapsedRealtime();
2596        final long uptime = SystemClock.uptimeMillis();
2597        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
2598    }
2599
2600    public void noteProcessCrashLocked(String name, int uid) {
2601        uid = mapUid(uid);
2602        if (isOnBattery()) {
2603            Uid u = getUidStatsLocked(uid);
2604            u.getProcessStatsLocked(name).incNumCrashesLocked();
2605        }
2606    }
2607
2608    public void noteProcessAnrLocked(String name, int uid) {
2609        uid = mapUid(uid);
2610        if (isOnBattery()) {
2611            Uid u = getUidStatsLocked(uid);
2612            u.getProcessStatsLocked(name).incNumAnrsLocked();
2613        }
2614    }
2615
2616    public void noteProcessStateLocked(String name, int uid, int state) {
2617        uid = mapUid(uid);
2618        final long elapsedRealtime = SystemClock.elapsedRealtime();
2619        getUidStatsLocked(uid).updateProcessStateLocked(name, state, elapsedRealtime);
2620    }
2621
2622    public void noteProcessFinishLocked(String name, int uid) {
2623        uid = mapUid(uid);
2624        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
2625            return;
2626        }
2627        final long elapsedRealtime = SystemClock.elapsedRealtime();
2628        final long uptime = SystemClock.uptimeMillis();
2629        getUidStatsLocked(uid).updateProcessStateLocked(name, Uid.PROCESS_STATE_NONE,
2630                elapsedRealtime);
2631        if (!mRecordAllHistory) {
2632            return;
2633        }
2634        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
2635    }
2636
2637    public void noteSyncStartLocked(String name, int uid) {
2638        uid = mapUid(uid);
2639        final long elapsedRealtime = SystemClock.elapsedRealtime();
2640        final long uptime = SystemClock.uptimeMillis();
2641        getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
2642        if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
2643            return;
2644        }
2645        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
2646    }
2647
2648    public void noteSyncFinishLocked(String name, int uid) {
2649        uid = mapUid(uid);
2650        final long elapsedRealtime = SystemClock.elapsedRealtime();
2651        final long uptime = SystemClock.uptimeMillis();
2652        getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
2653        if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
2654            return;
2655        }
2656        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
2657    }
2658
2659    public void noteJobStartLocked(String name, int uid) {
2660        uid = mapUid(uid);
2661        final long elapsedRealtime = SystemClock.elapsedRealtime();
2662        final long uptime = SystemClock.uptimeMillis();
2663        getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
2664        if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
2665            return;
2666        }
2667        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
2668    }
2669
2670    public void noteJobFinishLocked(String name, int uid) {
2671        uid = mapUid(uid);
2672        final long elapsedRealtime = SystemClock.elapsedRealtime();
2673        final long uptime = SystemClock.uptimeMillis();
2674        getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
2675        if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
2676            return;
2677        }
2678        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
2679    }
2680
2681    public void noteAlarmStartLocked(String name, int uid) {
2682        if (!mRecordAllHistory) {
2683            return;
2684        }
2685        uid = mapUid(uid);
2686        final long elapsedRealtime = SystemClock.elapsedRealtime();
2687        final long uptime = SystemClock.uptimeMillis();
2688        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_START, name, uid, 0)) {
2689            return;
2690        }
2691        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_START, name, uid);
2692    }
2693
2694    public void noteAlarmFinishLocked(String name, int uid) {
2695        if (!mRecordAllHistory) {
2696            return;
2697        }
2698        uid = mapUid(uid);
2699        final long elapsedRealtime = SystemClock.elapsedRealtime();
2700        final long uptime = SystemClock.uptimeMillis();
2701        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_FINISH, name, uid, 0)) {
2702            return;
2703        }
2704        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_FINISH, name, uid);
2705    }
2706
2707    private void requestWakelockCpuUpdate() {
2708        if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
2709            Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
2710            mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
2711        }
2712    }
2713
2714    private void requestImmediateCpuUpdate() {
2715        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
2716        mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
2717    }
2718
2719    public void setRecordAllHistoryLocked(boolean enabled) {
2720        mRecordAllHistory = enabled;
2721        if (!enabled) {
2722            // Clear out any existing state.
2723            mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
2724            mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
2725            // Record the currently running processes as stopping, now that we are no
2726            // longer tracking them.
2727            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
2728                    HistoryItem.EVENT_PROC);
2729            if (active != null) {
2730                long mSecRealtime = SystemClock.elapsedRealtime();
2731                final long mSecUptime = SystemClock.uptimeMillis();
2732                for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
2733                    SparseIntArray uids = ent.getValue();
2734                    for (int j=0; j<uids.size(); j++) {
2735                        addHistoryEventLocked(mSecRealtime, mSecUptime,
2736                                HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
2737                    }
2738                }
2739            }
2740        } else {
2741            // Record the currently running processes as starting, now that we are tracking them.
2742            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
2743                    HistoryItem.EVENT_PROC);
2744            if (active != null) {
2745                long mSecRealtime = SystemClock.elapsedRealtime();
2746                final long mSecUptime = SystemClock.uptimeMillis();
2747                for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
2748                    SparseIntArray uids = ent.getValue();
2749                    for (int j=0; j<uids.size(); j++) {
2750                        addHistoryEventLocked(mSecRealtime, mSecUptime,
2751                                HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
2752                    }
2753                }
2754            }
2755        }
2756    }
2757
2758    public void setNoAutoReset(boolean enabled) {
2759        mNoAutoReset = enabled;
2760    }
2761
2762    private String mInitialAcquireWakeName;
2763    private int mInitialAcquireWakeUid = -1;
2764
2765    public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
2766            boolean unimportantForLogging, long elapsedRealtime, long uptime) {
2767        uid = mapUid(uid);
2768        if (type == WAKE_TYPE_PARTIAL) {
2769            // Only care about partial wake locks, since full wake locks
2770            // will be canceled when the user puts the screen to sleep.
2771            aggregateLastWakeupUptimeLocked(uptime);
2772            if (historyName == null) {
2773                historyName = name;
2774            }
2775            if (mRecordAllHistory) {
2776                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
2777                        uid, 0)) {
2778                    addHistoryEventLocked(elapsedRealtime, uptime,
2779                            HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
2780                }
2781            }
2782            if (mWakeLockNesting == 0) {
2783                mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
2784                if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
2785                        + Integer.toHexString(mHistoryCur.states));
2786                mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
2787                mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
2788                mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
2789                mWakeLockImportant = !unimportantForLogging;
2790                addHistoryRecordLocked(elapsedRealtime, uptime);
2791            } else if (!mWakeLockImportant && !unimportantForLogging
2792                    && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
2793                if (mHistoryLastWritten.wakelockTag != null) {
2794                    // We'll try to update the last tag.
2795                    mHistoryLastWritten.wakelockTag = null;
2796                    mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
2797                    mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
2798                    mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
2799                    addHistoryRecordLocked(elapsedRealtime, uptime);
2800                }
2801                mWakeLockImportant = true;
2802            }
2803            mWakeLockNesting++;
2804        }
2805        if (uid >= 0) {
2806            if (mOnBatteryScreenOffTimeBase.isRunning()) {
2807                // We only update the cpu time when a wake lock is acquired if the screen is off.
2808                // If the screen is on, we don't distribute the power amongst partial wakelocks.
2809                if (DEBUG_ENERGY_CPU) {
2810                    Slog.d(TAG, "Updating cpu time because of +wake_lock");
2811                }
2812                requestWakelockCpuUpdate();
2813            }
2814            getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
2815        }
2816    }
2817
2818    public void noteStopWakeLocked(int uid, int pid, String name, String historyName, int type,
2819            long elapsedRealtime, long uptime) {
2820        uid = mapUid(uid);
2821        if (type == WAKE_TYPE_PARTIAL) {
2822            mWakeLockNesting--;
2823            if (mRecordAllHistory) {
2824                if (historyName == null) {
2825                    historyName = name;
2826                }
2827                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
2828                        uid, 0)) {
2829                    addHistoryEventLocked(elapsedRealtime, uptime,
2830                            HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
2831                }
2832            }
2833            if (mWakeLockNesting == 0) {
2834                mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
2835                if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
2836                        + Integer.toHexString(mHistoryCur.states));
2837                mInitialAcquireWakeName = null;
2838                mInitialAcquireWakeUid = -1;
2839                addHistoryRecordLocked(elapsedRealtime, uptime);
2840            }
2841        }
2842        if (uid >= 0) {
2843            if (mOnBatteryScreenOffTimeBase.isRunning()) {
2844                if (DEBUG_ENERGY_CPU) {
2845                    Slog.d(TAG, "Updating cpu time because of -wake_lock");
2846                }
2847                requestWakelockCpuUpdate();
2848            }
2849            getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
2850        }
2851    }
2852
2853    public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
2854            String historyName, int type, boolean unimportantForLogging) {
2855        final long elapsedRealtime = SystemClock.elapsedRealtime();
2856        final long uptime = SystemClock.uptimeMillis();
2857        final int N = ws.size();
2858        for (int i=0; i<N; i++) {
2859            noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
2860                    elapsedRealtime, uptime);
2861        }
2862    }
2863
2864    public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
2865            String historyName, int type, WorkSource newWs, int newPid, String newName,
2866            String newHistoryName, int newType, boolean newUnimportantForLogging) {
2867        final long elapsedRealtime = SystemClock.elapsedRealtime();
2868        final long uptime = SystemClock.uptimeMillis();
2869        // For correct semantics, we start the need worksources first, so that we won't
2870        // make inappropriate history items as if all wake locks went away and new ones
2871        // appeared.  This is okay because tracking of wake locks allows nesting.
2872        final int NN = newWs.size();
2873        for (int i=0; i<NN; i++) {
2874            noteStartWakeLocked(newWs.get(i), newPid, newName, newHistoryName, newType,
2875                    newUnimportantForLogging, elapsedRealtime, uptime);
2876        }
2877        final int NO = ws.size();
2878        for (int i=0; i<NO; i++) {
2879            noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
2880        }
2881    }
2882
2883    public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
2884            String historyName, int type) {
2885        final long elapsedRealtime = SystemClock.elapsedRealtime();
2886        final long uptime = SystemClock.uptimeMillis();
2887        final int N = ws.size();
2888        for (int i=0; i<N; i++) {
2889            noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
2890        }
2891    }
2892
2893    void aggregateLastWakeupUptimeLocked(long uptimeMs) {
2894        if (mLastWakeupReason != null) {
2895            long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
2896            SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
2897            timer.addCurrentReportedCount(1);
2898            timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds
2899            mLastWakeupReason = null;
2900        }
2901    }
2902
2903    public void noteWakeupReasonLocked(String reason) {
2904        final long elapsedRealtime = SystemClock.elapsedRealtime();
2905        final long uptime = SystemClock.uptimeMillis();
2906        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
2907                + Integer.toHexString(mHistoryCur.states));
2908        aggregateLastWakeupUptimeLocked(uptime);
2909        mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
2910        mHistoryCur.wakeReasonTag.string = reason;
2911        mHistoryCur.wakeReasonTag.uid = 0;
2912        mLastWakeupReason = reason;
2913        mLastWakeupUptimeMs = uptime;
2914        addHistoryRecordLocked(elapsedRealtime, uptime);
2915    }
2916
2917    public boolean startAddingCpuLocked() {
2918        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
2919        return mOnBatteryInternal;
2920    }
2921
2922    public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
2923                                      int statSystemTime, int statIOWaitTime, int statIrqTime,
2924                                      int statSoftIrqTime, int statIdleTime) {
2925        if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
2926                + " user=" + statUserTime + " sys=" + statSystemTime
2927                + " io=" + statIOWaitTime + " irq=" + statIrqTime
2928                + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
2929        mCurStepCpuUserTime += totalUTime;
2930        mCurStepCpuSystemTime += totalSTime;
2931        mCurStepStatUserTime += statUserTime;
2932        mCurStepStatSystemTime += statSystemTime;
2933        mCurStepStatIOWaitTime += statIOWaitTime;
2934        mCurStepStatIrqTime += statIrqTime;
2935        mCurStepStatSoftIrqTime += statSoftIrqTime;
2936        mCurStepStatIdleTime += statIdleTime;
2937    }
2938
2939    public void noteProcessDiedLocked(int uid, int pid) {
2940        uid = mapUid(uid);
2941        Uid u = mUidStats.get(uid);
2942        if (u != null) {
2943            u.mPids.remove(pid);
2944        }
2945    }
2946
2947    public long getProcessWakeTime(int uid, int pid, long realtime) {
2948        uid = mapUid(uid);
2949        Uid u = mUidStats.get(uid);
2950        if (u != null) {
2951            Uid.Pid p = u.mPids.get(pid);
2952            if (p != null) {
2953                return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
2954            }
2955        }
2956        return 0;
2957    }
2958
2959    public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) {
2960        uid = mapUid(uid);
2961        Uid u = mUidStats.get(uid);
2962        if (u != null) {
2963            u.reportExcessiveWakeLocked(proc, overTime, usedTime);
2964        }
2965    }
2966
2967    public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
2968        uid = mapUid(uid);
2969        Uid u = mUidStats.get(uid);
2970        if (u != null) {
2971            u.reportExcessiveCpuLocked(proc, overTime, usedTime);
2972        }
2973    }
2974
2975    int mSensorNesting;
2976
2977    public void noteStartSensorLocked(int uid, int sensor) {
2978        uid = mapUid(uid);
2979        final long elapsedRealtime = SystemClock.elapsedRealtime();
2980        final long uptime = SystemClock.uptimeMillis();
2981        if (mSensorNesting == 0) {
2982            mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
2983            if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
2984                    + Integer.toHexString(mHistoryCur.states));
2985            addHistoryRecordLocked(elapsedRealtime, uptime);
2986        }
2987        mSensorNesting++;
2988        getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
2989    }
2990
2991    public void noteStopSensorLocked(int uid, int sensor) {
2992        uid = mapUid(uid);
2993        final long elapsedRealtime = SystemClock.elapsedRealtime();
2994        final long uptime = SystemClock.uptimeMillis();
2995        mSensorNesting--;
2996        if (mSensorNesting == 0) {
2997            mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
2998            if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
2999                    + Integer.toHexString(mHistoryCur.states));
3000            addHistoryRecordLocked(elapsedRealtime, uptime);
3001        }
3002        getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
3003    }
3004
3005    int mGpsNesting;
3006
3007    public void noteStartGpsLocked(int uid) {
3008        uid = mapUid(uid);
3009        final long elapsedRealtime = SystemClock.elapsedRealtime();
3010        final long uptime = SystemClock.uptimeMillis();
3011        if (mGpsNesting == 0) {
3012            mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
3013            if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
3014                    + Integer.toHexString(mHistoryCur.states));
3015            addHistoryRecordLocked(elapsedRealtime, uptime);
3016        }
3017        mGpsNesting++;
3018        getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
3019    }
3020
3021    public void noteStopGpsLocked(int uid) {
3022        uid = mapUid(uid);
3023        final long elapsedRealtime = SystemClock.elapsedRealtime();
3024        final long uptime = SystemClock.uptimeMillis();
3025        mGpsNesting--;
3026        if (mGpsNesting == 0) {
3027            mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
3028            if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
3029                    + Integer.toHexString(mHistoryCur.states));
3030            addHistoryRecordLocked(elapsedRealtime, uptime);
3031        }
3032        getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
3033    }
3034
3035    public void noteScreenStateLocked(int state) {
3036        if (mScreenState != state) {
3037            recordDailyStatsIfNeededLocked(true);
3038            final int oldState = mScreenState;
3039            mScreenState = state;
3040            if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
3041                    + ", newState=" + Display.stateToString(state));
3042
3043            if (state != Display.STATE_UNKNOWN) {
3044                int stepState = state-1;
3045                if (stepState < 4) {
3046                    mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
3047                    mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
3048                } else {
3049                    Slog.wtf(TAG, "Unexpected screen state: " + state);
3050                }
3051            }
3052
3053            if (state == Display.STATE_ON) {
3054                // Screen turning on.
3055                final long elapsedRealtime = SystemClock.elapsedRealtime();
3056                final long uptime = SystemClock.uptimeMillis();
3057                mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
3058                if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
3059                        + Integer.toHexString(mHistoryCur.states));
3060                addHistoryRecordLocked(elapsedRealtime, uptime);
3061                mScreenOnTimer.startRunningLocked(elapsedRealtime);
3062                if (mScreenBrightnessBin >= 0) {
3063                    mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
3064                }
3065
3066                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
3067                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
3068
3069                // Fake a wake lock, so we consider the device waked as long
3070                // as the screen is on.
3071                noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
3072                        elapsedRealtime, uptime);
3073
3074                // Update discharge amounts.
3075                if (mOnBatteryInternal) {
3076                    updateDischargeScreenLevelsLocked(false, true);
3077                }
3078            } else if (oldState == Display.STATE_ON) {
3079                // Screen turning off or dozing.
3080                final long elapsedRealtime = SystemClock.elapsedRealtime();
3081                final long uptime = SystemClock.uptimeMillis();
3082                mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
3083                if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
3084                        + Integer.toHexString(mHistoryCur.states));
3085                addHistoryRecordLocked(elapsedRealtime, uptime);
3086                mScreenOnTimer.stopRunningLocked(elapsedRealtime);
3087                if (mScreenBrightnessBin >= 0) {
3088                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
3089                }
3090
3091                noteStopWakeLocked(-1, -1, "screen", "screen", WAKE_TYPE_PARTIAL,
3092                        elapsedRealtime, uptime);
3093
3094                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
3095                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
3096
3097                // Update discharge amounts.
3098                if (mOnBatteryInternal) {
3099                    updateDischargeScreenLevelsLocked(true, false);
3100                }
3101            }
3102        }
3103    }
3104
3105    public void noteScreenBrightnessLocked(int brightness) {
3106        // Bin the brightness.
3107        int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
3108        if (bin < 0) bin = 0;
3109        else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
3110        if (mScreenBrightnessBin != bin) {
3111            final long elapsedRealtime = SystemClock.elapsedRealtime();
3112            final long uptime = SystemClock.uptimeMillis();
3113            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
3114                    | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
3115            if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
3116                    + Integer.toHexString(mHistoryCur.states));
3117            addHistoryRecordLocked(elapsedRealtime, uptime);
3118            if (mScreenState == Display.STATE_ON) {
3119                if (mScreenBrightnessBin >= 0) {
3120                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
3121                }
3122                mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
3123            }
3124            mScreenBrightnessBin = bin;
3125        }
3126    }
3127
3128    public void noteUserActivityLocked(int uid, int event) {
3129        if (mOnBatteryInternal) {
3130            uid = mapUid(uid);
3131            getUidStatsLocked(uid).noteUserActivityLocked(event);
3132        }
3133    }
3134
3135    public void noteWakeUpLocked(String reason, int reasonUid) {
3136        final long elapsedRealtime = SystemClock.elapsedRealtime();
3137        final long uptime = SystemClock.uptimeMillis();
3138        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
3139                reason, reasonUid);
3140    }
3141
3142    public void noteInteractiveLocked(boolean interactive) {
3143        if (mInteractive != interactive) {
3144            final long elapsedRealtime = SystemClock.elapsedRealtime();
3145            mInteractive = interactive;
3146            if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
3147            if (interactive) {
3148                mInteractiveTimer.startRunningLocked(elapsedRealtime);
3149            } else {
3150                mInteractiveTimer.stopRunningLocked(elapsedRealtime);
3151            }
3152        }
3153    }
3154
3155    public void noteConnectivityChangedLocked(int type, String extra) {
3156        final long elapsedRealtime = SystemClock.elapsedRealtime();
3157        final long uptime = SystemClock.uptimeMillis();
3158        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
3159                extra, type);
3160        mNumConnectivityChange++;
3161    }
3162
3163    public void noteMobileRadioPowerState(int powerState, long timestampNs) {
3164        final long elapsedRealtime = SystemClock.elapsedRealtime();
3165        final long uptime = SystemClock.uptimeMillis();
3166        if (mMobileRadioPowerState != powerState) {
3167            long realElapsedRealtimeMs;
3168            final boolean active =
3169                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
3170                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
3171            if (active) {
3172                mMobileRadioActiveStartTime = realElapsedRealtimeMs = elapsedRealtime;
3173                mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
3174            } else {
3175                realElapsedRealtimeMs = timestampNs / (1000*1000);
3176                long lastUpdateTimeMs = mMobileRadioActiveStartTime;
3177                if (realElapsedRealtimeMs < lastUpdateTimeMs) {
3178                    Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
3179                            + " is before start time " + lastUpdateTimeMs);
3180                    realElapsedRealtimeMs = elapsedRealtime;
3181                } else if (realElapsedRealtimeMs < elapsedRealtime) {
3182                    mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
3183                            - realElapsedRealtimeMs);
3184                }
3185                mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
3186            }
3187            if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
3188                    + Integer.toHexString(mHistoryCur.states));
3189            addHistoryRecordLocked(elapsedRealtime, uptime);
3190            mMobileRadioPowerState = powerState;
3191            if (active) {
3192                mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
3193                mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
3194            } else {
3195                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
3196                updateMobileRadioStateLocked(realElapsedRealtimeMs);
3197                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
3198            }
3199        }
3200    }
3201
3202    public void notePowerSaveMode(boolean enabled) {
3203        if (mPowerSaveModeEnabled != enabled) {
3204            int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
3205            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
3206            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
3207            final long elapsedRealtime = SystemClock.elapsedRealtime();
3208            final long uptime = SystemClock.uptimeMillis();
3209            mPowerSaveModeEnabled = enabled;
3210            if (enabled) {
3211                mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
3212                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
3213                        + Integer.toHexString(mHistoryCur.states2));
3214                mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
3215            } else {
3216                mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
3217                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
3218                        + Integer.toHexString(mHistoryCur.states2));
3219                mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
3220            }
3221            addHistoryRecordLocked(elapsedRealtime, uptime);
3222        }
3223    }
3224
3225    public void noteDeviceIdleModeLocked(boolean enabled, String activeReason, int activeUid) {
3226        final long elapsedRealtime = SystemClock.elapsedRealtime();
3227        final long uptime = SystemClock.uptimeMillis();
3228        boolean nowIdling = enabled;
3229        if (mDeviceIdling && !enabled && activeReason == null) {
3230            // We don't go out of general idling mode until explicitly taken out of
3231            // device idle through going active or significant motion.
3232            nowIdling = true;
3233        }
3234        if (mDeviceIdling != nowIdling) {
3235            mDeviceIdling = nowIdling;
3236            int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
3237            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
3238            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
3239            if (enabled) {
3240                mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
3241            } else {
3242                mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
3243            }
3244        }
3245        if (mDeviceIdleModeEnabled != enabled) {
3246            mDeviceIdleModeEnabled = enabled;
3247            addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
3248                    activeReason != null ? activeReason : "", activeUid);
3249            if (enabled) {
3250                mHistoryCur.states2 |= HistoryItem.STATE2_DEVICE_IDLE_FLAG;
3251                if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode enabled to: "
3252                        + Integer.toHexString(mHistoryCur.states2));
3253                mDeviceIdleModeEnabledTimer.startRunningLocked(elapsedRealtime);
3254            } else {
3255                mHistoryCur.states2 &= ~HistoryItem.STATE2_DEVICE_IDLE_FLAG;
3256                if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode disabled to: "
3257                        + Integer.toHexString(mHistoryCur.states2));
3258                mDeviceIdleModeEnabledTimer.stopRunningLocked(elapsedRealtime);
3259            }
3260            addHistoryRecordLocked(elapsedRealtime, uptime);
3261        }
3262    }
3263
3264    public void notePackageInstalledLocked(String pkgName, int versionCode) {
3265        final long elapsedRealtime = SystemClock.elapsedRealtime();
3266        final long uptime = SystemClock.uptimeMillis();
3267        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
3268                pkgName, versionCode);
3269        PackageChange pc = new PackageChange();
3270        pc.mPackageName = pkgName;
3271        pc.mUpdate = true;
3272        pc.mVersionCode = versionCode;
3273        addPackageChange(pc);
3274    }
3275
3276    public void notePackageUninstalledLocked(String pkgName) {
3277        final long elapsedRealtime = SystemClock.elapsedRealtime();
3278        final long uptime = SystemClock.uptimeMillis();
3279        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
3280                pkgName, 0);
3281        PackageChange pc = new PackageChange();
3282        pc.mPackageName = pkgName;
3283        pc.mUpdate = true;
3284        addPackageChange(pc);
3285    }
3286
3287    private void addPackageChange(PackageChange pc) {
3288        if (mDailyPackageChanges == null) {
3289            mDailyPackageChanges = new ArrayList<>();
3290        }
3291        mDailyPackageChanges.add(pc);
3292    }
3293
3294    public void notePhoneOnLocked() {
3295        if (!mPhoneOn) {
3296            final long elapsedRealtime = SystemClock.elapsedRealtime();
3297            final long uptime = SystemClock.uptimeMillis();
3298            mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
3299            if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
3300                    + Integer.toHexString(mHistoryCur.states));
3301            addHistoryRecordLocked(elapsedRealtime, uptime);
3302            mPhoneOn = true;
3303            mPhoneOnTimer.startRunningLocked(elapsedRealtime);
3304        }
3305    }
3306
3307    public void notePhoneOffLocked() {
3308        if (mPhoneOn) {
3309            final long elapsedRealtime = SystemClock.elapsedRealtime();
3310            final long uptime = SystemClock.uptimeMillis();
3311            mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
3312            if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
3313                    + Integer.toHexString(mHistoryCur.states));
3314            addHistoryRecordLocked(elapsedRealtime, uptime);
3315            mPhoneOn = false;
3316            mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
3317        }
3318    }
3319
3320    void stopAllPhoneSignalStrengthTimersLocked(int except) {
3321        final long elapsedRealtime = SystemClock.elapsedRealtime();
3322        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
3323            if (i == except) {
3324                continue;
3325            }
3326            while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
3327                mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
3328            }
3329        }
3330    }
3331
3332    private int fixPhoneServiceState(int state, int signalBin) {
3333        if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
3334            // In this case we will always be STATE_OUT_OF_SERVICE, so need
3335            // to infer that we are scanning from other data.
3336            if (state == ServiceState.STATE_OUT_OF_SERVICE
3337                    && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
3338                state = ServiceState.STATE_IN_SERVICE;
3339            }
3340        }
3341
3342        return state;
3343    }
3344
3345    private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
3346        boolean scanning = false;
3347        boolean newHistory = false;
3348
3349        mPhoneServiceStateRaw = state;
3350        mPhoneSimStateRaw = simState;
3351        mPhoneSignalStrengthBinRaw = strengthBin;
3352
3353        final long elapsedRealtime = SystemClock.elapsedRealtime();
3354        final long uptime = SystemClock.uptimeMillis();
3355
3356        if (simState == TelephonyManager.SIM_STATE_ABSENT) {
3357            // In this case we will always be STATE_OUT_OF_SERVICE, so need
3358            // to infer that we are scanning from other data.
3359            if (state == ServiceState.STATE_OUT_OF_SERVICE
3360                    && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
3361                state = ServiceState.STATE_IN_SERVICE;
3362            }
3363        }
3364
3365        // If the phone is powered off, stop all timers.
3366        if (state == ServiceState.STATE_POWER_OFF) {
3367            strengthBin = -1;
3368
3369        // If we are in service, make sure the correct signal string timer is running.
3370        } else if (state == ServiceState.STATE_IN_SERVICE) {
3371            // Bin will be changed below.
3372
3373        // If we're out of service, we are in the lowest signal strength
3374        // bin and have the scanning bit set.
3375        } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
3376            scanning = true;
3377            strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
3378            if (!mPhoneSignalScanningTimer.isRunningLocked()) {
3379                mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
3380                newHistory = true;
3381                if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
3382                        + Integer.toHexString(mHistoryCur.states));
3383                mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
3384            }
3385        }
3386
3387        if (!scanning) {
3388            // If we are no longer scanning, then stop the scanning timer.
3389            if (mPhoneSignalScanningTimer.isRunningLocked()) {
3390                mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
3391                if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
3392                        + Integer.toHexString(mHistoryCur.states));
3393                newHistory = true;
3394                mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
3395            }
3396        }
3397
3398        if (mPhoneServiceState != state) {
3399            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
3400                    | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
3401            if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
3402                    + Integer.toHexString(mHistoryCur.states));
3403            newHistory = true;
3404            mPhoneServiceState = state;
3405        }
3406
3407        if (mPhoneSignalStrengthBin != strengthBin) {
3408            if (mPhoneSignalStrengthBin >= 0) {
3409                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
3410                        elapsedRealtime);
3411            }
3412            if (strengthBin >= 0) {
3413                if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
3414                    mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
3415                }
3416                mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
3417                        | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
3418                if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
3419                        + Integer.toHexString(mHistoryCur.states));
3420                newHistory = true;
3421            } else {
3422                stopAllPhoneSignalStrengthTimersLocked(-1);
3423            }
3424            mPhoneSignalStrengthBin = strengthBin;
3425        }
3426
3427        if (newHistory) {
3428            addHistoryRecordLocked(elapsedRealtime, uptime);
3429        }
3430    }
3431
3432    /**
3433     * Telephony stack updates the phone state.
3434     * @param state phone state from ServiceState.getState()
3435     */
3436    public void notePhoneStateLocked(int state, int simState) {
3437        updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
3438    }
3439
3440    public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
3441        // Bin the strength.
3442        int bin = signalStrength.getLevel();
3443        updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
3444    }
3445
3446    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
3447        int bin = DATA_CONNECTION_NONE;
3448        if (hasData) {
3449            switch (dataType) {
3450                case TelephonyManager.NETWORK_TYPE_EDGE:
3451                    bin = DATA_CONNECTION_EDGE;
3452                    break;
3453                case TelephonyManager.NETWORK_TYPE_GPRS:
3454                    bin = DATA_CONNECTION_GPRS;
3455                    break;
3456                case TelephonyManager.NETWORK_TYPE_UMTS:
3457                    bin = DATA_CONNECTION_UMTS;
3458                    break;
3459                case TelephonyManager.NETWORK_TYPE_CDMA:
3460                    bin = DATA_CONNECTION_CDMA;
3461                    break;
3462                case TelephonyManager.NETWORK_TYPE_EVDO_0:
3463                    bin = DATA_CONNECTION_EVDO_0;
3464                    break;
3465                case TelephonyManager.NETWORK_TYPE_EVDO_A:
3466                    bin = DATA_CONNECTION_EVDO_A;
3467                    break;
3468                case TelephonyManager.NETWORK_TYPE_1xRTT:
3469                    bin = DATA_CONNECTION_1xRTT;
3470                    break;
3471                case TelephonyManager.NETWORK_TYPE_HSDPA:
3472                    bin = DATA_CONNECTION_HSDPA;
3473                    break;
3474                case TelephonyManager.NETWORK_TYPE_HSUPA:
3475                    bin = DATA_CONNECTION_HSUPA;
3476                    break;
3477                case TelephonyManager.NETWORK_TYPE_HSPA:
3478                    bin = DATA_CONNECTION_HSPA;
3479                    break;
3480                case TelephonyManager.NETWORK_TYPE_IDEN:
3481                    bin = DATA_CONNECTION_IDEN;
3482                    break;
3483                case TelephonyManager.NETWORK_TYPE_EVDO_B:
3484                    bin = DATA_CONNECTION_EVDO_B;
3485                    break;
3486                case TelephonyManager.NETWORK_TYPE_LTE:
3487                    bin = DATA_CONNECTION_LTE;
3488                    break;
3489                case TelephonyManager.NETWORK_TYPE_EHRPD:
3490                    bin = DATA_CONNECTION_EHRPD;
3491                    break;
3492                case TelephonyManager.NETWORK_TYPE_HSPAP:
3493                    bin = DATA_CONNECTION_HSPAP;
3494                    break;
3495                default:
3496                    bin = DATA_CONNECTION_OTHER;
3497                    break;
3498            }
3499        }
3500        if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
3501        if (mPhoneDataConnectionType != bin) {
3502            final long elapsedRealtime = SystemClock.elapsedRealtime();
3503            final long uptime = SystemClock.uptimeMillis();
3504            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
3505                    | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
3506            if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
3507                    + Integer.toHexString(mHistoryCur.states));
3508            addHistoryRecordLocked(elapsedRealtime, uptime);
3509            if (mPhoneDataConnectionType >= 0) {
3510                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
3511                        elapsedRealtime);
3512            }
3513            mPhoneDataConnectionType = bin;
3514            mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
3515        }
3516    }
3517
3518    public void noteWifiOnLocked() {
3519        if (!mWifiOn) {
3520            final long elapsedRealtime = SystemClock.elapsedRealtime();
3521            final long uptime = SystemClock.uptimeMillis();
3522            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
3523            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
3524                    + Integer.toHexString(mHistoryCur.states));
3525            addHistoryRecordLocked(elapsedRealtime, uptime);
3526            mWifiOn = true;
3527            mWifiOnTimer.startRunningLocked(elapsedRealtime);
3528            scheduleSyncExternalWifiStatsLocked("wifi-off");
3529        }
3530    }
3531
3532    public void noteWifiOffLocked() {
3533        final long elapsedRealtime = SystemClock.elapsedRealtime();
3534        final long uptime = SystemClock.uptimeMillis();
3535        if (mWifiOn) {
3536            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
3537            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
3538                    + Integer.toHexString(mHistoryCur.states));
3539            addHistoryRecordLocked(elapsedRealtime, uptime);
3540            mWifiOn = false;
3541            mWifiOnTimer.stopRunningLocked(elapsedRealtime);
3542            scheduleSyncExternalWifiStatsLocked("wifi-on");
3543        }
3544    }
3545
3546    public void noteAudioOnLocked(int uid) {
3547        uid = mapUid(uid);
3548        final long elapsedRealtime = SystemClock.elapsedRealtime();
3549        final long uptime = SystemClock.uptimeMillis();
3550        if (mAudioOnNesting == 0) {
3551            mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
3552            if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
3553                    + Integer.toHexString(mHistoryCur.states));
3554            addHistoryRecordLocked(elapsedRealtime, uptime);
3555            mAudioOnTimer.startRunningLocked(elapsedRealtime);
3556        }
3557        mAudioOnNesting++;
3558        getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
3559    }
3560
3561    public void noteAudioOffLocked(int uid) {
3562        if (mAudioOnNesting == 0) {
3563            return;
3564        }
3565        uid = mapUid(uid);
3566        final long elapsedRealtime = SystemClock.elapsedRealtime();
3567        final long uptime = SystemClock.uptimeMillis();
3568        if (--mAudioOnNesting == 0) {
3569            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
3570            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
3571                    + Integer.toHexString(mHistoryCur.states));
3572            addHistoryRecordLocked(elapsedRealtime, uptime);
3573            mAudioOnTimer.stopRunningLocked(elapsedRealtime);
3574        }
3575        getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
3576    }
3577
3578    public void noteVideoOnLocked(int uid) {
3579        uid = mapUid(uid);
3580        final long elapsedRealtime = SystemClock.elapsedRealtime();
3581        final long uptime = SystemClock.uptimeMillis();
3582        if (mVideoOnNesting == 0) {
3583            mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
3584            if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
3585                    + Integer.toHexString(mHistoryCur.states));
3586            addHistoryRecordLocked(elapsedRealtime, uptime);
3587            mVideoOnTimer.startRunningLocked(elapsedRealtime);
3588        }
3589        mVideoOnNesting++;
3590        getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
3591    }
3592
3593    public void noteVideoOffLocked(int uid) {
3594        if (mVideoOnNesting == 0) {
3595            return;
3596        }
3597        uid = mapUid(uid);
3598        final long elapsedRealtime = SystemClock.elapsedRealtime();
3599        final long uptime = SystemClock.uptimeMillis();
3600        if (--mVideoOnNesting == 0) {
3601            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
3602            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
3603                    + Integer.toHexString(mHistoryCur.states));
3604            addHistoryRecordLocked(elapsedRealtime, uptime);
3605            mVideoOnTimer.stopRunningLocked(elapsedRealtime);
3606        }
3607        getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
3608    }
3609
3610    public void noteResetAudioLocked() {
3611        if (mAudioOnNesting > 0) {
3612            final long elapsedRealtime = SystemClock.elapsedRealtime();
3613            final long uptime = SystemClock.uptimeMillis();
3614            mAudioOnNesting = 0;
3615            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
3616            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
3617                    + Integer.toHexString(mHistoryCur.states));
3618            addHistoryRecordLocked(elapsedRealtime, uptime);
3619            mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
3620            for (int i=0; i<mUidStats.size(); i++) {
3621                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3622                uid.noteResetAudioLocked(elapsedRealtime);
3623            }
3624        }
3625    }
3626
3627    public void noteResetVideoLocked() {
3628        if (mVideoOnNesting > 0) {
3629            final long elapsedRealtime = SystemClock.elapsedRealtime();
3630            final long uptime = SystemClock.uptimeMillis();
3631            mAudioOnNesting = 0;
3632            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
3633            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
3634                    + Integer.toHexString(mHistoryCur.states));
3635            addHistoryRecordLocked(elapsedRealtime, uptime);
3636            mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
3637            for (int i=0; i<mUidStats.size(); i++) {
3638                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3639                uid.noteResetVideoLocked(elapsedRealtime);
3640            }
3641        }
3642    }
3643
3644    public void noteActivityResumedLocked(int uid) {
3645        uid = mapUid(uid);
3646        getUidStatsLocked(uid).noteActivityResumedLocked(SystemClock.elapsedRealtime());
3647    }
3648
3649    public void noteActivityPausedLocked(int uid) {
3650        uid = mapUid(uid);
3651        getUidStatsLocked(uid).noteActivityPausedLocked(SystemClock.elapsedRealtime());
3652    }
3653
3654    public void noteVibratorOnLocked(int uid, long durationMillis) {
3655        uid = mapUid(uid);
3656        getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
3657    }
3658
3659    public void noteVibratorOffLocked(int uid) {
3660        uid = mapUid(uid);
3661        getUidStatsLocked(uid).noteVibratorOffLocked();
3662    }
3663
3664    public void noteFlashlightOnLocked(int uid) {
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 on to: "
3671                    + Integer.toHexString(mHistoryCur.states2));
3672            addHistoryRecordLocked(elapsedRealtime, uptime);
3673            mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
3674        }
3675        getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
3676    }
3677
3678    public void noteFlashlightOffLocked(int uid) {
3679        if (mFlashlightOnNesting == 0) {
3680            return;
3681        }
3682        uid = mapUid(uid);
3683        final long elapsedRealtime = SystemClock.elapsedRealtime();
3684        final long uptime = SystemClock.uptimeMillis();
3685        if (--mFlashlightOnNesting == 0) {
3686            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
3687            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
3688                    + Integer.toHexString(mHistoryCur.states2));
3689            addHistoryRecordLocked(elapsedRealtime, uptime);
3690            mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
3691        }
3692        getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
3693    }
3694
3695    public void noteCameraOnLocked(int uid) {
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 on to: "
3702                    + Integer.toHexString(mHistoryCur.states2));
3703            addHistoryRecordLocked(elapsedRealtime, uptime);
3704            mCameraOnTimer.startRunningLocked(elapsedRealtime);
3705        }
3706        getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
3707    }
3708
3709    public void noteCameraOffLocked(int uid) {
3710        if (mCameraOnNesting == 0) {
3711            return;
3712        }
3713        uid = mapUid(uid);
3714        final long elapsedRealtime = SystemClock.elapsedRealtime();
3715        final long uptime = SystemClock.uptimeMillis();
3716        if (--mCameraOnNesting == 0) {
3717            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
3718            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
3719                    + Integer.toHexString(mHistoryCur.states2));
3720            addHistoryRecordLocked(elapsedRealtime, uptime);
3721            mCameraOnTimer.stopRunningLocked(elapsedRealtime);
3722        }
3723        getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
3724    }
3725
3726    public void noteResetCameraLocked() {
3727        if (mCameraOnNesting > 0) {
3728            final long elapsedRealtime = SystemClock.elapsedRealtime();
3729            final long uptime = SystemClock.uptimeMillis();
3730            mCameraOnNesting = 0;
3731            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
3732            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
3733                    + Integer.toHexString(mHistoryCur.states2));
3734            addHistoryRecordLocked(elapsedRealtime, uptime);
3735            mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
3736            for (int i=0; i<mUidStats.size(); i++) {
3737                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3738                uid.noteResetCameraLocked(elapsedRealtime);
3739            }
3740        }
3741    }
3742
3743    public void noteResetFlashlightLocked() {
3744        if (mFlashlightOnNesting > 0) {
3745            final long elapsedRealtime = SystemClock.elapsedRealtime();
3746            final long uptime = SystemClock.uptimeMillis();
3747            mFlashlightOnNesting = 0;
3748            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
3749            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
3750                    + Integer.toHexString(mHistoryCur.states2));
3751            addHistoryRecordLocked(elapsedRealtime, uptime);
3752            mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
3753            for (int i=0; i<mUidStats.size(); i++) {
3754                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3755                uid.noteResetFlashlightLocked(elapsedRealtime);
3756            }
3757        }
3758    }
3759
3760    public void noteWifiRadioPowerState(int powerState, long timestampNs) {
3761        final long elapsedRealtime = SystemClock.elapsedRealtime();
3762        final long uptime = SystemClock.uptimeMillis();
3763        if (mWifiRadioPowerState != powerState) {
3764            final boolean active =
3765                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
3766                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
3767            if (active) {
3768                mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
3769            } else {
3770                mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
3771            }
3772            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
3773                    + Integer.toHexString(mHistoryCur.states));
3774            addHistoryRecordLocked(elapsedRealtime, uptime);
3775            mWifiRadioPowerState = powerState;
3776        }
3777    }
3778
3779    public void noteWifiRunningLocked(WorkSource ws) {
3780        if (!mGlobalWifiRunning) {
3781            final long elapsedRealtime = SystemClock.elapsedRealtime();
3782            final long uptime = SystemClock.uptimeMillis();
3783            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
3784            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
3785                    + Integer.toHexString(mHistoryCur.states));
3786            addHistoryRecordLocked(elapsedRealtime, uptime);
3787            mGlobalWifiRunning = true;
3788            mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
3789            int N = ws.size();
3790            for (int i=0; i<N; i++) {
3791                int uid = mapUid(ws.get(i));
3792                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
3793            }
3794            scheduleSyncExternalWifiStatsLocked("wifi-running");
3795        } else {
3796            Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
3797        }
3798    }
3799
3800    public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
3801        if (mGlobalWifiRunning) {
3802            final long elapsedRealtime = SystemClock.elapsedRealtime();
3803            int N = oldWs.size();
3804            for (int i=0; i<N; i++) {
3805                int uid = mapUid(oldWs.get(i));
3806                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
3807            }
3808            N = newWs.size();
3809            for (int i=0; i<N; i++) {
3810                int uid = mapUid(newWs.get(i));
3811                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
3812            }
3813        } else {
3814            Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
3815        }
3816    }
3817
3818    public void noteWifiStoppedLocked(WorkSource ws) {
3819        if (mGlobalWifiRunning) {
3820            final long elapsedRealtime = SystemClock.elapsedRealtime();
3821            final long uptime = SystemClock.uptimeMillis();
3822            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
3823            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
3824                    + Integer.toHexString(mHistoryCur.states));
3825            addHistoryRecordLocked(elapsedRealtime, uptime);
3826            mGlobalWifiRunning = false;
3827            mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
3828            int N = ws.size();
3829            for (int i=0; i<N; i++) {
3830                int uid = mapUid(ws.get(i));
3831                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
3832            }
3833            scheduleSyncExternalWifiStatsLocked("wifi-stopped");
3834        } else {
3835            Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
3836        }
3837    }
3838
3839    public void noteWifiStateLocked(int wifiState, String accessPoint) {
3840        if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
3841        if (mWifiState != wifiState) {
3842            final long elapsedRealtime = SystemClock.elapsedRealtime();
3843            if (mWifiState >= 0) {
3844                mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
3845            }
3846            mWifiState = wifiState;
3847            mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
3848            scheduleSyncExternalWifiStatsLocked("wifi-state");
3849        }
3850    }
3851
3852    public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
3853        if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
3854        if (mWifiSupplState != supplState) {
3855            final long elapsedRealtime = SystemClock.elapsedRealtime();
3856            final long uptime = SystemClock.uptimeMillis();
3857            if (mWifiSupplState >= 0) {
3858                mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
3859            }
3860            mWifiSupplState = supplState;
3861            mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
3862            mHistoryCur.states2 =
3863                    (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
3864                    | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
3865            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
3866                    + Integer.toHexString(mHistoryCur.states2));
3867            addHistoryRecordLocked(elapsedRealtime, uptime);
3868        }
3869    }
3870
3871    void stopAllWifiSignalStrengthTimersLocked(int except) {
3872        final long elapsedRealtime = SystemClock.elapsedRealtime();
3873        for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
3874            if (i == except) {
3875                continue;
3876            }
3877            while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
3878                mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
3879            }
3880        }
3881    }
3882
3883    public void noteWifiRssiChangedLocked(int newRssi) {
3884        int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
3885        if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
3886        if (mWifiSignalStrengthBin != strengthBin) {
3887            final long elapsedRealtime = SystemClock.elapsedRealtime();
3888            final long uptime = SystemClock.uptimeMillis();
3889            if (mWifiSignalStrengthBin >= 0) {
3890                mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
3891                        elapsedRealtime);
3892            }
3893            if (strengthBin >= 0) {
3894                if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
3895                    mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
3896                }
3897                mHistoryCur.states2 =
3898                        (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
3899                        | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
3900                if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
3901                        + Integer.toHexString(mHistoryCur.states2));
3902                addHistoryRecordLocked(elapsedRealtime, uptime);
3903            } else {
3904                stopAllWifiSignalStrengthTimersLocked(-1);
3905            }
3906            mWifiSignalStrengthBin = strengthBin;
3907        }
3908    }
3909
3910    int mWifiFullLockNesting = 0;
3911
3912    public void noteFullWifiLockAcquiredLocked(int uid) {
3913        uid = mapUid(uid);
3914        final long elapsedRealtime = SystemClock.elapsedRealtime();
3915        final long uptime = SystemClock.uptimeMillis();
3916        if (mWifiFullLockNesting == 0) {
3917            mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
3918            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
3919                    + Integer.toHexString(mHistoryCur.states));
3920            addHistoryRecordLocked(elapsedRealtime, uptime);
3921        }
3922        mWifiFullLockNesting++;
3923        getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
3924    }
3925
3926    public void noteFullWifiLockReleasedLocked(int uid) {
3927        uid = mapUid(uid);
3928        final long elapsedRealtime = SystemClock.elapsedRealtime();
3929        final long uptime = SystemClock.uptimeMillis();
3930        mWifiFullLockNesting--;
3931        if (mWifiFullLockNesting == 0) {
3932            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
3933            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
3934                    + Integer.toHexString(mHistoryCur.states));
3935            addHistoryRecordLocked(elapsedRealtime, uptime);
3936        }
3937        getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
3938    }
3939
3940    int mWifiScanNesting = 0;
3941
3942    public void noteWifiScanStartedLocked(int uid) {
3943        uid = mapUid(uid);
3944        final long elapsedRealtime = SystemClock.elapsedRealtime();
3945        final long uptime = SystemClock.uptimeMillis();
3946        if (mWifiScanNesting == 0) {
3947            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
3948            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
3949                    + Integer.toHexString(mHistoryCur.states));
3950            addHistoryRecordLocked(elapsedRealtime, uptime);
3951        }
3952        mWifiScanNesting++;
3953        getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
3954    }
3955
3956    public void noteWifiScanStoppedLocked(int uid) {
3957        uid = mapUid(uid);
3958        final long elapsedRealtime = SystemClock.elapsedRealtime();
3959        final long uptime = SystemClock.uptimeMillis();
3960        mWifiScanNesting--;
3961        if (mWifiScanNesting == 0) {
3962            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
3963            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
3964                    + Integer.toHexString(mHistoryCur.states));
3965            addHistoryRecordLocked(elapsedRealtime, uptime);
3966        }
3967        getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
3968    }
3969
3970    public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
3971        uid = mapUid(uid);
3972        final long elapsedRealtime = SystemClock.elapsedRealtime();
3973        getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
3974    }
3975
3976    public void noteWifiBatchedScanStoppedLocked(int uid) {
3977        uid = mapUid(uid);
3978        final long elapsedRealtime = SystemClock.elapsedRealtime();
3979        getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
3980    }
3981
3982    int mWifiMulticastNesting = 0;
3983
3984    public void noteWifiMulticastEnabledLocked(int uid) {
3985        uid = mapUid(uid);
3986        final long elapsedRealtime = SystemClock.elapsedRealtime();
3987        final long uptime = SystemClock.uptimeMillis();
3988        if (mWifiMulticastNesting == 0) {
3989            mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
3990            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
3991                    + Integer.toHexString(mHistoryCur.states));
3992            addHistoryRecordLocked(elapsedRealtime, uptime);
3993        }
3994        mWifiMulticastNesting++;
3995        getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
3996    }
3997
3998    public void noteWifiMulticastDisabledLocked(int uid) {
3999        uid = mapUid(uid);
4000        final long elapsedRealtime = SystemClock.elapsedRealtime();
4001        final long uptime = SystemClock.uptimeMillis();
4002        mWifiMulticastNesting--;
4003        if (mWifiMulticastNesting == 0) {
4004            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
4005            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
4006                    + Integer.toHexString(mHistoryCur.states));
4007            addHistoryRecordLocked(elapsedRealtime, uptime);
4008        }
4009        getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
4010    }
4011
4012    public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
4013        int N = ws.size();
4014        for (int i=0; i<N; i++) {
4015            noteFullWifiLockAcquiredLocked(ws.get(i));
4016        }
4017    }
4018
4019    public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
4020        int N = ws.size();
4021        for (int i=0; i<N; i++) {
4022            noteFullWifiLockReleasedLocked(ws.get(i));
4023        }
4024    }
4025
4026    public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
4027        int N = ws.size();
4028        for (int i=0; i<N; i++) {
4029            noteWifiScanStartedLocked(ws.get(i));
4030        }
4031    }
4032
4033    public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
4034        int N = ws.size();
4035        for (int i=0; i<N; i++) {
4036            noteWifiScanStoppedLocked(ws.get(i));
4037        }
4038    }
4039
4040    public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
4041        int N = ws.size();
4042        for (int i=0; i<N; i++) {
4043            noteWifiBatchedScanStartedLocked(ws.get(i), csph);
4044        }
4045    }
4046
4047    public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
4048        int N = ws.size();
4049        for (int i=0; i<N; i++) {
4050            noteWifiBatchedScanStoppedLocked(ws.get(i));
4051        }
4052    }
4053
4054    public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
4055        int N = ws.size();
4056        for (int i=0; i<N; i++) {
4057            noteWifiMulticastEnabledLocked(ws.get(i));
4058        }
4059    }
4060
4061    public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
4062        int N = ws.size();
4063        for (int i=0; i<N; i++) {
4064            noteWifiMulticastDisabledLocked(ws.get(i));
4065        }
4066    }
4067
4068    private static String[] includeInStringArray(String[] array, String str) {
4069        if (ArrayUtils.indexOf(array, str) >= 0) {
4070            return array;
4071        }
4072        String[] newArray = new String[array.length+1];
4073        System.arraycopy(array, 0, newArray, 0, array.length);
4074        newArray[array.length] = str;
4075        return newArray;
4076    }
4077
4078    private static String[] excludeFromStringArray(String[] array, String str) {
4079        int index = ArrayUtils.indexOf(array, str);
4080        if (index >= 0) {
4081            String[] newArray = new String[array.length-1];
4082            if (index > 0) {
4083                System.arraycopy(array, 0, newArray, 0, index);
4084            }
4085            if (index < array.length-1) {
4086                System.arraycopy(array, index+1, newArray, index, array.length-index-1);
4087            }
4088            return newArray;
4089        }
4090        return array;
4091    }
4092
4093    public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
4094        if (TextUtils.isEmpty(iface)) return;
4095        if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
4096            mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
4097            if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
4098        } else {
4099            mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
4100            if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
4101        }
4102        if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
4103            mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
4104            if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
4105        } else {
4106            mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
4107            if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
4108        }
4109    }
4110
4111    public void noteNetworkStatsEnabledLocked() {
4112        // During device boot, qtaguid isn't enabled until after the inital
4113        // loading of battery stats. Now that they're enabled, take our initial
4114        // snapshot for future delta calculation.
4115        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
4116        updateMobileRadioStateLocked(elapsedRealtimeMs);
4117        updateWifiStateLocked(null);
4118    }
4119
4120    @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
4121        return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4122    }
4123
4124    @Override public int getScreenOnCount(int which) {
4125        return mScreenOnTimer.getCountLocked(which);
4126    }
4127
4128    @Override public long getScreenBrightnessTime(int brightnessBin,
4129            long elapsedRealtimeUs, int which) {
4130        return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
4131                elapsedRealtimeUs, which);
4132    }
4133
4134    @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
4135        return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4136    }
4137
4138    @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
4139        return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4140    }
4141
4142    @Override public int getPowerSaveModeEnabledCount(int which) {
4143        return mPowerSaveModeEnabledTimer.getCountLocked(which);
4144    }
4145
4146    @Override public long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which) {
4147        return mDeviceIdleModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4148    }
4149
4150    @Override public int getDeviceIdleModeEnabledCount(int which) {
4151        return mDeviceIdleModeEnabledTimer.getCountLocked(which);
4152    }
4153
4154    @Override public long getDeviceIdlingTime(long elapsedRealtimeUs, int which) {
4155        return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4156    }
4157
4158    @Override public int getDeviceIdlingCount(int which) {
4159        return mDeviceIdlingTimer.getCountLocked(which);
4160    }
4161
4162    @Override public int getNumConnectivityChange(int which) {
4163        int val = mNumConnectivityChange;
4164        if (which == STATS_CURRENT) {
4165            val -= mLoadedNumConnectivityChange;
4166        } else if (which == STATS_SINCE_UNPLUGGED) {
4167            val -= mUnpluggedNumConnectivityChange;
4168        }
4169        return val;
4170    }
4171
4172    @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
4173        return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4174    }
4175
4176    @Override public int getPhoneOnCount(int which) {
4177        return mPhoneOnTimer.getCountLocked(which);
4178    }
4179
4180    @Override public long getPhoneSignalStrengthTime(int strengthBin,
4181            long elapsedRealtimeUs, int which) {
4182        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
4183                elapsedRealtimeUs, which);
4184    }
4185
4186    @Override public long getPhoneSignalScanningTime(
4187            long elapsedRealtimeUs, int which) {
4188        return mPhoneSignalScanningTimer.getTotalTimeLocked(
4189                elapsedRealtimeUs, which);
4190    }
4191
4192    @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
4193        return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
4194    }
4195
4196    @Override public long getPhoneDataConnectionTime(int dataType,
4197            long elapsedRealtimeUs, int which) {
4198        return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
4199                elapsedRealtimeUs, which);
4200    }
4201
4202    @Override public int getPhoneDataConnectionCount(int dataType, int which) {
4203        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
4204    }
4205
4206    @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
4207        return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4208    }
4209
4210    @Override public int getMobileRadioActiveCount(int which) {
4211        return mMobileRadioActiveTimer.getCountLocked(which);
4212    }
4213
4214    @Override public long getMobileRadioActiveAdjustedTime(int which) {
4215        return mMobileRadioActiveAdjustedTime.getCountLocked(which);
4216    }
4217
4218    @Override public long getMobileRadioActiveUnknownTime(int which) {
4219        return mMobileRadioActiveUnknownTime.getCountLocked(which);
4220    }
4221
4222    @Override public int getMobileRadioActiveUnknownCount(int which) {
4223        return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
4224    }
4225
4226    @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
4227        return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4228    }
4229
4230    @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
4231        return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4232    }
4233
4234    @Override public long getWifiStateTime(int wifiState,
4235            long elapsedRealtimeUs, int which) {
4236        return mWifiStateTimer[wifiState].getTotalTimeLocked(
4237                elapsedRealtimeUs, which);
4238    }
4239
4240    @Override public int getWifiStateCount(int wifiState, int which) {
4241        return mWifiStateTimer[wifiState].getCountLocked(which);
4242    }
4243
4244    @Override public long getWifiSupplStateTime(int state,
4245            long elapsedRealtimeUs, int which) {
4246        return mWifiSupplStateTimer[state].getTotalTimeLocked(
4247                elapsedRealtimeUs, which);
4248    }
4249
4250    @Override public int getWifiSupplStateCount(int state, int which) {
4251        return mWifiSupplStateTimer[state].getCountLocked(which);
4252    }
4253
4254    @Override public long getWifiSignalStrengthTime(int strengthBin,
4255            long elapsedRealtimeUs, int which) {
4256        return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
4257                elapsedRealtimeUs, which);
4258    }
4259
4260    @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
4261        return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
4262    }
4263
4264    @Override public boolean hasBluetoothActivityReporting() {
4265        return mHasBluetoothEnergyReporting;
4266    }
4267
4268    @Override public long getBluetoothControllerActivity(int type, int which) {
4269        if (type >= 0 && type < mBluetoothActivityCounters.length) {
4270            return mBluetoothActivityCounters[type].getCountLocked(which);
4271        }
4272        return 0;
4273    }
4274
4275    @Override public boolean hasWifiActivityReporting() {
4276        return mHasWifiEnergyReporting;
4277    }
4278
4279    @Override public long getWifiControllerActivity(int type, int which) {
4280        if (type >= 0 && type < mWifiActivityCounters.length) {
4281            return mWifiActivityCounters[type].getCountLocked(which);
4282        }
4283        return 0;
4284    }
4285
4286    @Override
4287    public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
4288        return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4289    }
4290
4291    @Override
4292    public long getFlashlightOnCount(int which) {
4293        return mFlashlightOnTimer.getCountLocked(which);
4294    }
4295
4296    @Override
4297    public long getCameraOnTime(long elapsedRealtimeUs, int which) {
4298        return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4299    }
4300
4301    @Override
4302    public long getNetworkActivityBytes(int type, int which) {
4303        if (type >= 0 && type < mNetworkByteActivityCounters.length) {
4304            return mNetworkByteActivityCounters[type].getCountLocked(which);
4305        } else {
4306            return 0;
4307        }
4308    }
4309
4310    @Override
4311    public long getNetworkActivityPackets(int type, int which) {
4312        if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
4313            return mNetworkPacketActivityCounters[type].getCountLocked(which);
4314        } else {
4315            return 0;
4316        }
4317    }
4318
4319    @Override public long getStartClockTime() {
4320        final long currentTime = System.currentTimeMillis();
4321        if (ensureStartClockTime(currentTime)) {
4322            recordCurrentTimeChangeLocked(currentTime, SystemClock.elapsedRealtime(),
4323                    SystemClock.uptimeMillis());
4324        }
4325        return mStartClockTime;
4326    }
4327
4328    @Override public String getStartPlatformVersion() {
4329        return mStartPlatformVersion;
4330    }
4331
4332    @Override public String getEndPlatformVersion() {
4333        return mEndPlatformVersion;
4334    }
4335
4336    @Override public int getParcelVersion() {
4337        return VERSION;
4338    }
4339
4340    @Override public boolean getIsOnBattery() {
4341        return mOnBattery;
4342    }
4343
4344    @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
4345        return mUidStats;
4346    }
4347
4348    /**
4349     * The statistics associated with a particular uid.
4350     */
4351    public final class Uid extends BatteryStats.Uid {
4352
4353        final int mUid;
4354
4355        boolean mWifiRunning;
4356        StopwatchTimer mWifiRunningTimer;
4357
4358        boolean mFullWifiLockOut;
4359        StopwatchTimer mFullWifiLockTimer;
4360
4361        boolean mWifiScanStarted;
4362        StopwatchTimer mWifiScanTimer;
4363
4364        static final int NO_BATCHED_SCAN_STARTED = -1;
4365        int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
4366        StopwatchTimer[] mWifiBatchedScanTimer;
4367
4368        boolean mWifiMulticastEnabled;
4369        StopwatchTimer mWifiMulticastTimer;
4370
4371        StopwatchTimer mAudioTurnedOnTimer;
4372        StopwatchTimer mVideoTurnedOnTimer;
4373        StopwatchTimer mFlashlightTurnedOnTimer;
4374        StopwatchTimer mCameraTurnedOnTimer;
4375
4376
4377        StopwatchTimer mForegroundActivityTimer;
4378
4379        static final int PROCESS_STATE_NONE = NUM_PROCESS_STATE;
4380        int mProcessState = PROCESS_STATE_NONE;
4381        StopwatchTimer[] mProcessStateTimer;
4382
4383        BatchTimer mVibratorOnTimer;
4384
4385        Counter[] mUserActivityCounters;
4386
4387        LongSamplingCounter[] mNetworkByteActivityCounters;
4388        LongSamplingCounter[] mNetworkPacketActivityCounters;
4389        LongSamplingCounter mMobileRadioActiveTime;
4390        LongSamplingCounter mMobileRadioActiveCount;
4391
4392        /**
4393         * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
4394         */
4395        LongSamplingCounter[] mWifiControllerTime =
4396                new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
4397
4398        /**
4399         * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
4400         */
4401        LongSamplingCounter[] mBluetoothControllerTime =
4402                new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
4403
4404        /**
4405         * The CPU times we had at the last history details update.
4406         */
4407        long mLastStepUserTime;
4408        long mLastStepSystemTime;
4409        long mCurStepUserTime;
4410        long mCurStepSystemTime;
4411
4412        LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
4413        LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
4414        LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase);
4415        LongSamplingCounter[] mSpeedBins;
4416
4417        /**
4418         * The statistics we have collected for this uid's wake locks.
4419         */
4420        final OverflowArrayMap<Wakelock> mWakelockStats = new OverflowArrayMap<Wakelock>() {
4421            @Override public Wakelock instantiateObject() { return new Wakelock(); }
4422        };
4423
4424        /**
4425         * The statistics we have collected for this uid's syncs.
4426         */
4427        final OverflowArrayMap<StopwatchTimer> mSyncStats = new OverflowArrayMap<StopwatchTimer>() {
4428            @Override public StopwatchTimer instantiateObject() {
4429                return new StopwatchTimer(Uid.this, SYNC, null, mOnBatteryTimeBase);
4430            }
4431        };
4432
4433        /**
4434         * The statistics we have collected for this uid's jobs.
4435         */
4436        final OverflowArrayMap<StopwatchTimer> mJobStats = new OverflowArrayMap<StopwatchTimer>() {
4437            @Override public StopwatchTimer instantiateObject() {
4438                return new StopwatchTimer(Uid.this, JOB, null, mOnBatteryTimeBase);
4439            }
4440        };
4441
4442        /**
4443         * The statistics we have collected for this uid's sensor activations.
4444         */
4445        final SparseArray<Sensor> mSensorStats = new SparseArray<>();
4446
4447        /**
4448         * The statistics we have collected for this uid's processes.
4449         */
4450        final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
4451
4452        /**
4453         * The statistics we have collected for this uid's processes.
4454         */
4455        final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
4456
4457        /**
4458         * The transient wake stats we have collected for this uid's pids.
4459         */
4460        final SparseArray<Pid> mPids = new SparseArray<>();
4461
4462        public Uid(int uid) {
4463            mUid = uid;
4464            mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
4465                    mWifiRunningTimers, mOnBatteryTimeBase);
4466            mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
4467                    mFullWifiLockTimers, mOnBatteryTimeBase);
4468            mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
4469                    mWifiScanTimers, mOnBatteryTimeBase);
4470            mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
4471            mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
4472                    mWifiMulticastTimers, mOnBatteryTimeBase);
4473            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
4474            mSpeedBins = new LongSamplingCounter[getCpuSpeedSteps()];
4475        }
4476
4477        @Override
4478        public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
4479            return mWakelockStats.getMap();
4480        }
4481
4482        @Override
4483        public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
4484            return mSyncStats.getMap();
4485        }
4486
4487        @Override
4488        public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
4489            return mJobStats.getMap();
4490        }
4491
4492        @Override
4493        public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
4494            return mSensorStats;
4495        }
4496
4497        @Override
4498        public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
4499            return mProcessStats;
4500        }
4501
4502        @Override
4503        public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
4504            return mPackageStats;
4505        }
4506
4507        @Override
4508        public int getUid() {
4509            return mUid;
4510        }
4511
4512        @Override
4513        public void noteWifiRunningLocked(long elapsedRealtimeMs) {
4514            if (!mWifiRunning) {
4515                mWifiRunning = true;
4516                if (mWifiRunningTimer == null) {
4517                    mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
4518                            mWifiRunningTimers, mOnBatteryTimeBase);
4519                }
4520                mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
4521            }
4522        }
4523
4524        @Override
4525        public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
4526            if (mWifiRunning) {
4527                mWifiRunning = false;
4528                mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
4529            }
4530        }
4531
4532        @Override
4533        public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
4534            if (!mFullWifiLockOut) {
4535                mFullWifiLockOut = true;
4536                if (mFullWifiLockTimer == null) {
4537                    mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
4538                            mFullWifiLockTimers, mOnBatteryTimeBase);
4539                }
4540                mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
4541            }
4542        }
4543
4544        @Override
4545        public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
4546            if (mFullWifiLockOut) {
4547                mFullWifiLockOut = false;
4548                mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
4549            }
4550        }
4551
4552        @Override
4553        public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
4554            if (!mWifiScanStarted) {
4555                mWifiScanStarted = true;
4556                if (mWifiScanTimer == null) {
4557                    mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
4558                            mWifiScanTimers, mOnBatteryTimeBase);
4559                }
4560                mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
4561            }
4562        }
4563
4564        @Override
4565        public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
4566            if (mWifiScanStarted) {
4567                mWifiScanStarted = false;
4568                mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
4569            }
4570        }
4571
4572        @Override
4573        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
4574            int bin = 0;
4575            while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
4576                csph = csph >> 3;
4577                bin++;
4578            }
4579
4580            if (mWifiBatchedScanBinStarted == bin) return;
4581
4582            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
4583                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
4584                        stopRunningLocked(elapsedRealtimeMs);
4585            }
4586            mWifiBatchedScanBinStarted = bin;
4587            if (mWifiBatchedScanTimer[bin] == null) {
4588                makeWifiBatchedScanBin(bin, null);
4589            }
4590            mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
4591        }
4592
4593        @Override
4594        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
4595            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
4596                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
4597                        stopRunningLocked(elapsedRealtimeMs);
4598                mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
4599            }
4600        }
4601
4602        @Override
4603        public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
4604            if (!mWifiMulticastEnabled) {
4605                mWifiMulticastEnabled = true;
4606                if (mWifiMulticastTimer == null) {
4607                    mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
4608                            mWifiMulticastTimers, mOnBatteryTimeBase);
4609                }
4610                mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
4611            }
4612        }
4613
4614        @Override
4615        public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
4616            if (mWifiMulticastEnabled) {
4617                mWifiMulticastEnabled = false;
4618                mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
4619            }
4620        }
4621
4622        public void noteWifiControllerActivityLocked(int type, long timeMs) {
4623            if (mWifiControllerTime[type] == null) {
4624                mWifiControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase);
4625            }
4626            mWifiControllerTime[type].addCountLocked(timeMs);
4627        }
4628
4629        public StopwatchTimer createAudioTurnedOnTimerLocked() {
4630            if (mAudioTurnedOnTimer == null) {
4631                mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
4632                        mAudioTurnedOnTimers, mOnBatteryTimeBase);
4633            }
4634            return mAudioTurnedOnTimer;
4635        }
4636
4637        public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
4638            createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4639        }
4640
4641        public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
4642            if (mAudioTurnedOnTimer != null) {
4643                mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4644            }
4645        }
4646
4647        public void noteResetAudioLocked(long elapsedRealtimeMs) {
4648            if (mAudioTurnedOnTimer != null) {
4649                mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4650            }
4651        }
4652
4653        public StopwatchTimer createVideoTurnedOnTimerLocked() {
4654            if (mVideoTurnedOnTimer == null) {
4655                mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
4656                        mVideoTurnedOnTimers, mOnBatteryTimeBase);
4657            }
4658            return mVideoTurnedOnTimer;
4659        }
4660
4661        public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
4662            createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4663        }
4664
4665        public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
4666            if (mVideoTurnedOnTimer != null) {
4667                mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4668            }
4669        }
4670
4671        public void noteResetVideoLocked(long elapsedRealtimeMs) {
4672            if (mVideoTurnedOnTimer != null) {
4673                mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4674            }
4675        }
4676
4677        public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
4678            if (mFlashlightTurnedOnTimer == null) {
4679                mFlashlightTurnedOnTimer = new StopwatchTimer(Uid.this, FLASHLIGHT_TURNED_ON,
4680                        mFlashlightTurnedOnTimers, mOnBatteryTimeBase);
4681            }
4682            return mFlashlightTurnedOnTimer;
4683        }
4684
4685        public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
4686            createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4687        }
4688
4689        public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
4690            if (mFlashlightTurnedOnTimer != null) {
4691                mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4692            }
4693        }
4694
4695        public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
4696            if (mFlashlightTurnedOnTimer != null) {
4697                mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4698            }
4699        }
4700
4701        public StopwatchTimer createCameraTurnedOnTimerLocked() {
4702            if (mCameraTurnedOnTimer == null) {
4703                mCameraTurnedOnTimer = new StopwatchTimer(Uid.this, CAMERA_TURNED_ON,
4704                        mCameraTurnedOnTimers, mOnBatteryTimeBase);
4705            }
4706            return mCameraTurnedOnTimer;
4707        }
4708
4709        public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
4710            createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4711        }
4712
4713        public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
4714            if (mCameraTurnedOnTimer != null) {
4715                mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4716            }
4717        }
4718
4719        public void noteResetCameraLocked(long elapsedRealtimeMs) {
4720            if (mCameraTurnedOnTimer != null) {
4721                mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4722            }
4723        }
4724
4725        public StopwatchTimer createForegroundActivityTimerLocked() {
4726            if (mForegroundActivityTimer == null) {
4727                mForegroundActivityTimer = new StopwatchTimer(
4728                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase);
4729            }
4730            return mForegroundActivityTimer;
4731        }
4732
4733        @Override
4734        public void noteActivityResumedLocked(long elapsedRealtimeMs) {
4735            // We always start, since we want multiple foreground PIDs to nest
4736            createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
4737        }
4738
4739        @Override
4740        public void noteActivityPausedLocked(long elapsedRealtimeMs) {
4741            if (mForegroundActivityTimer != null) {
4742                mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
4743            }
4744        }
4745
4746        void updateUidProcessStateLocked(int state, long elapsedRealtimeMs) {
4747            if (mProcessState == state) return;
4748
4749            if (mProcessState != PROCESS_STATE_NONE) {
4750                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
4751            }
4752            mProcessState = state;
4753            if (state != PROCESS_STATE_NONE) {
4754                if (mProcessStateTimer[state] == null) {
4755                    makeProcessState(state, null);
4756                }
4757                mProcessStateTimer[state].startRunningLocked(elapsedRealtimeMs);
4758            }
4759        }
4760
4761        public BatchTimer createVibratorOnTimerLocked() {
4762            if (mVibratorOnTimer == null) {
4763                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
4764            }
4765            return mVibratorOnTimer;
4766        }
4767
4768        public void noteVibratorOnLocked(long durationMillis) {
4769            createVibratorOnTimerLocked().addDuration(BatteryStatsImpl.this, durationMillis);
4770        }
4771
4772        public void noteVibratorOffLocked() {
4773            if (mVibratorOnTimer != null) {
4774                mVibratorOnTimer.abortLastDuration(BatteryStatsImpl.this);
4775            }
4776        }
4777
4778        @Override
4779        public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
4780            if (mWifiRunningTimer == null) {
4781                return 0;
4782            }
4783            return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4784        }
4785
4786        @Override
4787        public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
4788            if (mFullWifiLockTimer == null) {
4789                return 0;
4790            }
4791            return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4792        }
4793
4794        @Override
4795        public long getWifiScanTime(long elapsedRealtimeUs, int which) {
4796            if (mWifiScanTimer == null) {
4797                return 0;
4798            }
4799            return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4800        }
4801
4802        @Override
4803        public int getWifiScanCount(int which) {
4804            if (mWifiScanTimer == null) {
4805                return 0;
4806            }
4807            return mWifiScanTimer.getCountLocked(which);
4808        }
4809
4810        @Override
4811        public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, 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].getTotalTimeLocked(elapsedRealtimeUs, which);
4817        }
4818
4819        @Override
4820        public int getWifiBatchedScanCount(int csphBin, int which) {
4821            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
4822            if (mWifiBatchedScanTimer[csphBin] == null) {
4823                return 0;
4824            }
4825            return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
4826        }
4827
4828        @Override
4829        public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
4830            if (mWifiMulticastTimer == null) {
4831                return 0;
4832            }
4833            return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4834        }
4835
4836        @Override
4837        public Timer getAudioTurnedOnTimer() {
4838            return mAudioTurnedOnTimer;
4839        }
4840
4841        @Override
4842        public Timer getVideoTurnedOnTimer() {
4843            return mVideoTurnedOnTimer;
4844        }
4845
4846        @Override
4847        public Timer getFlashlightTurnedOnTimer() {
4848            return mFlashlightTurnedOnTimer;
4849        }
4850
4851        @Override
4852        public Timer getCameraTurnedOnTimer() {
4853            return mCameraTurnedOnTimer;
4854        }
4855
4856        @Override
4857        public Timer getForegroundActivityTimer() {
4858            return mForegroundActivityTimer;
4859        }
4860
4861        void makeProcessState(int i, Parcel in) {
4862            if (i < 0 || i >= NUM_PROCESS_STATE) return;
4863
4864            if (in == null) {
4865                mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
4866                        mOnBatteryTimeBase);
4867            } else {
4868                mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
4869                        mOnBatteryTimeBase, in);
4870            }
4871        }
4872
4873        @Override
4874        public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
4875            if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
4876            if (mProcessStateTimer[state] == null) {
4877                return 0;
4878            }
4879            return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
4880        }
4881
4882        @Override
4883        public Timer getVibratorOnTimer() {
4884            return mVibratorOnTimer;
4885        }
4886
4887        @Override
4888        public void noteUserActivityLocked(int type) {
4889            if (mUserActivityCounters == null) {
4890                initUserActivityLocked();
4891            }
4892            if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
4893                mUserActivityCounters[type].stepAtomic();
4894            } else {
4895                Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
4896                        new Throwable());
4897            }
4898        }
4899
4900        @Override
4901        public boolean hasUserActivity() {
4902            return mUserActivityCounters != null;
4903        }
4904
4905        @Override
4906        public int getUserActivityCount(int type, int which) {
4907            if (mUserActivityCounters == null) {
4908                return 0;
4909            }
4910            return mUserActivityCounters[type].getCountLocked(which);
4911        }
4912
4913        void makeWifiBatchedScanBin(int i, Parcel in) {
4914            if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
4915
4916            ArrayList<StopwatchTimer> collected = mWifiBatchedScanTimers.get(i);
4917            if (collected == null) {
4918                collected = new ArrayList<StopwatchTimer>();
4919                mWifiBatchedScanTimers.put(i, collected);
4920            }
4921            if (in == null) {
4922                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
4923                        mOnBatteryTimeBase);
4924            } else {
4925                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
4926                        mOnBatteryTimeBase, in);
4927            }
4928        }
4929
4930
4931        void initUserActivityLocked() {
4932            mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
4933            for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
4934                mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase);
4935            }
4936        }
4937
4938        void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
4939            if (mNetworkByteActivityCounters == null) {
4940                initNetworkActivityLocked();
4941            }
4942            if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
4943                mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
4944                mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
4945            } else {
4946                Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
4947                        new Throwable());
4948            }
4949        }
4950
4951        void noteMobileRadioActiveTimeLocked(long batteryUptime) {
4952            if (mNetworkByteActivityCounters == null) {
4953                initNetworkActivityLocked();
4954            }
4955            mMobileRadioActiveTime.addCountLocked(batteryUptime);
4956            mMobileRadioActiveCount.addCountLocked(1);
4957        }
4958
4959        @Override
4960        public boolean hasNetworkActivity() {
4961            return mNetworkByteActivityCounters != null;
4962        }
4963
4964        @Override
4965        public long getNetworkActivityBytes(int type, int which) {
4966            if (mNetworkByteActivityCounters != null && type >= 0
4967                    && type < mNetworkByteActivityCounters.length) {
4968                return mNetworkByteActivityCounters[type].getCountLocked(which);
4969            } else {
4970                return 0;
4971            }
4972        }
4973
4974        @Override
4975        public long getNetworkActivityPackets(int type, int which) {
4976            if (mNetworkPacketActivityCounters != null && type >= 0
4977                    && type < mNetworkPacketActivityCounters.length) {
4978                return mNetworkPacketActivityCounters[type].getCountLocked(which);
4979            } else {
4980                return 0;
4981            }
4982        }
4983
4984        @Override
4985        public long getMobileRadioActiveTime(int which) {
4986            return mMobileRadioActiveTime != null
4987                    ? mMobileRadioActiveTime.getCountLocked(which) : 0;
4988        }
4989
4990        @Override
4991        public int getMobileRadioActiveCount(int which) {
4992            return mMobileRadioActiveCount != null
4993                    ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
4994        }
4995
4996        @Override
4997        public long getUserCpuTimeUs(int which) {
4998            return mUserCpuTime.getCountLocked(which);
4999        }
5000
5001        @Override
5002        public long getSystemCpuTimeUs(int which) {
5003            return mSystemCpuTime.getCountLocked(which);
5004        }
5005
5006        @Override
5007        public long getCpuPowerMaUs(int which) {
5008            return mCpuPower.getCountLocked(which);
5009        }
5010
5011        @Override
5012        public long getTimeAtCpuSpeed(int step, int which) {
5013            if (step >= 0 && step < mSpeedBins.length) {
5014                if (mSpeedBins[step] != null) {
5015                    return mSpeedBins[step].getCountLocked(which);
5016                }
5017            }
5018            return 0;
5019        }
5020
5021        @Override
5022        public long getWifiControllerActivity(int type, int which) {
5023            if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES &&
5024                    mWifiControllerTime[type] != null) {
5025                return mWifiControllerTime[type].getCountLocked(which);
5026            }
5027            return 0;
5028        }
5029
5030        void initNetworkActivityLocked() {
5031            mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5032            mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5033            for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5034                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
5035                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
5036            }
5037            mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase);
5038            mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase);
5039        }
5040
5041        /**
5042         * Clear all stats for this uid.  Returns true if the uid is completely
5043         * inactive so can be dropped.
5044         */
5045        boolean reset() {
5046            boolean active = false;
5047
5048            if (mWifiRunningTimer != null) {
5049                active |= !mWifiRunningTimer.reset(false);
5050                active |= mWifiRunning;
5051            }
5052            if (mFullWifiLockTimer != null) {
5053                active |= !mFullWifiLockTimer.reset(false);
5054                active |= mFullWifiLockOut;
5055            }
5056            if (mWifiScanTimer != null) {
5057                active |= !mWifiScanTimer.reset(false);
5058                active |= mWifiScanStarted;
5059            }
5060            if (mWifiBatchedScanTimer != null) {
5061                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5062                    if (mWifiBatchedScanTimer[i] != null) {
5063                        active |= !mWifiBatchedScanTimer[i].reset(false);
5064                    }
5065                }
5066                active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
5067            }
5068            if (mWifiMulticastTimer != null) {
5069                active |= !mWifiMulticastTimer.reset(false);
5070                active |= mWifiMulticastEnabled;
5071            }
5072            if (mAudioTurnedOnTimer != null) {
5073                active |= !mAudioTurnedOnTimer.reset(false);
5074            }
5075            if (mVideoTurnedOnTimer != null) {
5076                active |= !mVideoTurnedOnTimer.reset(false);
5077            }
5078            if (mFlashlightTurnedOnTimer != null) {
5079                active |= !mFlashlightTurnedOnTimer.reset(false);
5080            }
5081            if (mCameraTurnedOnTimer != null) {
5082                active |= !mCameraTurnedOnTimer.reset(false);
5083            }
5084            if (mForegroundActivityTimer != null) {
5085                active |= !mForegroundActivityTimer.reset(false);
5086            }
5087            if (mProcessStateTimer != null) {
5088                for (int i = 0; i < NUM_PROCESS_STATE; i++) {
5089                    if (mProcessStateTimer[i] != null) {
5090                        active |= !mProcessStateTimer[i].reset(false);
5091                    }
5092                }
5093                active |= (mProcessState != PROCESS_STATE_NONE);
5094            }
5095            if (mVibratorOnTimer != null) {
5096                if (mVibratorOnTimer.reset(false)) {
5097                    mVibratorOnTimer.detach();
5098                    mVibratorOnTimer = null;
5099                } else {
5100                    active = true;
5101                }
5102            }
5103
5104            if (mUserActivityCounters != null) {
5105                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5106                    mUserActivityCounters[i].reset(false);
5107                }
5108            }
5109
5110            if (mNetworkByteActivityCounters != null) {
5111                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5112                    mNetworkByteActivityCounters[i].reset(false);
5113                    mNetworkPacketActivityCounters[i].reset(false);
5114                }
5115                mMobileRadioActiveTime.reset(false);
5116                mMobileRadioActiveCount.reset(false);
5117            }
5118
5119            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5120                if (mWifiControllerTime[i] != null) {
5121                    mWifiControllerTime[i].reset(false);
5122                }
5123
5124                if (mBluetoothControllerTime[i] != null) {
5125                    mBluetoothControllerTime[i].reset(false);
5126                }
5127            }
5128
5129            mUserCpuTime.reset(false);
5130            mSystemCpuTime.reset(false);
5131            mCpuPower.reset(false);
5132            for (int i = 0; i < mSpeedBins.length; i++) {
5133                LongSamplingCounter c = mSpeedBins[i];
5134                if (c != null) {
5135                    c.reset(false);
5136                }
5137            }
5138
5139            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
5140            for (int iw=wakeStats.size()-1; iw>=0; iw--) {
5141                Wakelock wl = wakeStats.valueAt(iw);
5142                if (wl.reset()) {
5143                    wakeStats.removeAt(iw);
5144                } else {
5145                    active = true;
5146                }
5147            }
5148            mWakelockStats.cleanup();
5149            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
5150            for (int is=syncStats.size()-1; is>=0; is--) {
5151                StopwatchTimer timer = syncStats.valueAt(is);
5152                if (timer.reset(false)) {
5153                    syncStats.removeAt(is);
5154                    timer.detach();
5155                } else {
5156                    active = true;
5157                }
5158            }
5159            mSyncStats.cleanup();
5160            final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
5161            for (int ij=jobStats.size()-1; ij>=0; ij--) {
5162                StopwatchTimer timer = jobStats.valueAt(ij);
5163                if (timer.reset(false)) {
5164                    jobStats.removeAt(ij);
5165                    timer.detach();
5166                } else {
5167                    active = true;
5168                }
5169            }
5170            mJobStats.cleanup();
5171            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
5172                Sensor s = mSensorStats.valueAt(ise);
5173                if (s.reset()) {
5174                    mSensorStats.removeAt(ise);
5175                } else {
5176                    active = true;
5177                }
5178            }
5179            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
5180                Proc proc = mProcessStats.valueAt(ip);
5181                if (proc.mProcessState == PROCESS_STATE_NONE) {
5182                    proc.detach();
5183                    mProcessStats.removeAt(ip);
5184                } else {
5185                    proc.reset();
5186                    active = true;
5187                }
5188            }
5189            if (mPids.size() > 0) {
5190                for (int i=mPids.size()-1; i>=0; i--) {
5191                    Pid pid = mPids.valueAt(i);
5192                    if (pid.mWakeNesting > 0) {
5193                        active = true;
5194                    } else {
5195                        mPids.removeAt(i);
5196                    }
5197                }
5198            }
5199            if (mPackageStats.size() > 0) {
5200                Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
5201                while (it.hasNext()) {
5202                    Map.Entry<String, Pkg> pkgEntry = it.next();
5203                    Pkg p = pkgEntry.getValue();
5204                    p.detach();
5205                    if (p.mServiceStats.size() > 0) {
5206                        Iterator<Map.Entry<String, Pkg.Serv>> it2
5207                                = p.mServiceStats.entrySet().iterator();
5208                        while (it2.hasNext()) {
5209                            Map.Entry<String, Pkg.Serv> servEntry = it2.next();
5210                            servEntry.getValue().detach();
5211                        }
5212                    }
5213                }
5214                mPackageStats.clear();
5215            }
5216
5217            mLastStepUserTime = mLastStepSystemTime = 0;
5218            mCurStepUserTime = mCurStepSystemTime = 0;
5219
5220            if (!active) {
5221                if (mWifiRunningTimer != null) {
5222                    mWifiRunningTimer.detach();
5223                }
5224                if (mFullWifiLockTimer != null) {
5225                    mFullWifiLockTimer.detach();
5226                }
5227                if (mWifiScanTimer != null) {
5228                    mWifiScanTimer.detach();
5229                }
5230                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5231                    if (mWifiBatchedScanTimer[i] != null) {
5232                        mWifiBatchedScanTimer[i].detach();
5233                    }
5234                }
5235                if (mWifiMulticastTimer != null) {
5236                    mWifiMulticastTimer.detach();
5237                }
5238                if (mAudioTurnedOnTimer != null) {
5239                    mAudioTurnedOnTimer.detach();
5240                    mAudioTurnedOnTimer = null;
5241                }
5242                if (mVideoTurnedOnTimer != null) {
5243                    mVideoTurnedOnTimer.detach();
5244                    mVideoTurnedOnTimer = null;
5245                }
5246                if (mFlashlightTurnedOnTimer != null) {
5247                    mFlashlightTurnedOnTimer.detach();
5248                    mFlashlightTurnedOnTimer = null;
5249                }
5250                if (mCameraTurnedOnTimer != null) {
5251                    mCameraTurnedOnTimer.detach();
5252                    mCameraTurnedOnTimer = null;
5253                }
5254                if (mForegroundActivityTimer != null) {
5255                    mForegroundActivityTimer.detach();
5256                    mForegroundActivityTimer = null;
5257                }
5258                if (mUserActivityCounters != null) {
5259                    for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5260                        mUserActivityCounters[i].detach();
5261                    }
5262                }
5263                if (mNetworkByteActivityCounters != null) {
5264                    for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5265                        mNetworkByteActivityCounters[i].detach();
5266                        mNetworkPacketActivityCounters[i].detach();
5267                    }
5268                }
5269
5270                for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5271                    if (mWifiControllerTime[i] != null) {
5272                        mWifiControllerTime[i].detach();
5273                    }
5274
5275                    if (mBluetoothControllerTime[i] != null) {
5276                        mBluetoothControllerTime[i].detach();
5277                    }
5278                }
5279                mPids.clear();
5280
5281                mUserCpuTime.detach();
5282                mSystemCpuTime.detach();
5283                mCpuPower.detach();
5284                for (int i = 0; i < mSpeedBins.length; i++) {
5285                    LongSamplingCounter c = mSpeedBins[i];
5286                    if (c != null) {
5287                        c.detach();
5288                    }
5289                }
5290            }
5291
5292            return !active;
5293        }
5294
5295        void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
5296            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
5297            int NW = wakeStats.size();
5298            out.writeInt(NW);
5299            for (int iw=0; iw<NW; iw++) {
5300                out.writeString(wakeStats.keyAt(iw));
5301                Uid.Wakelock wakelock = wakeStats.valueAt(iw);
5302                wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
5303            }
5304
5305            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
5306            int NS = syncStats.size();
5307            out.writeInt(NS);
5308            for (int is=0; is<NS; is++) {
5309                out.writeString(syncStats.keyAt(is));
5310                StopwatchTimer timer = syncStats.valueAt(is);
5311                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
5312            }
5313
5314            final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
5315            int NJ = jobStats.size();
5316            out.writeInt(NJ);
5317            for (int ij=0; ij<NJ; ij++) {
5318                out.writeString(jobStats.keyAt(ij));
5319                StopwatchTimer timer = jobStats.valueAt(ij);
5320                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
5321            }
5322
5323            int NSE = mSensorStats.size();
5324            out.writeInt(NSE);
5325            for (int ise=0; ise<NSE; ise++) {
5326                out.writeInt(mSensorStats.keyAt(ise));
5327                Uid.Sensor sensor = mSensorStats.valueAt(ise);
5328                sensor.writeToParcelLocked(out, elapsedRealtimeUs);
5329            }
5330
5331            int NP = mProcessStats.size();
5332            out.writeInt(NP);
5333            for (int ip=0; ip<NP; ip++) {
5334                out.writeString(mProcessStats.keyAt(ip));
5335                Uid.Proc proc = mProcessStats.valueAt(ip);
5336                proc.writeToParcelLocked(out);
5337            }
5338
5339            out.writeInt(mPackageStats.size());
5340            for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
5341                out.writeString(pkgEntry.getKey());
5342                Uid.Pkg pkg = pkgEntry.getValue();
5343                pkg.writeToParcelLocked(out);
5344            }
5345
5346            if (mWifiRunningTimer != null) {
5347                out.writeInt(1);
5348                mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
5349            } else {
5350                out.writeInt(0);
5351            }
5352            if (mFullWifiLockTimer != null) {
5353                out.writeInt(1);
5354                mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
5355            } else {
5356                out.writeInt(0);
5357            }
5358            if (mWifiScanTimer != null) {
5359                out.writeInt(1);
5360                mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
5361            } else {
5362                out.writeInt(0);
5363            }
5364            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5365                if (mWifiBatchedScanTimer[i] != null) {
5366                    out.writeInt(1);
5367                    mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
5368                } else {
5369                    out.writeInt(0);
5370                }
5371            }
5372            if (mWifiMulticastTimer != null) {
5373                out.writeInt(1);
5374                mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
5375            } else {
5376                out.writeInt(0);
5377            }
5378
5379            if (mAudioTurnedOnTimer != null) {
5380                out.writeInt(1);
5381                mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5382            } else {
5383                out.writeInt(0);
5384            }
5385            if (mVideoTurnedOnTimer != null) {
5386                out.writeInt(1);
5387                mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5388            } else {
5389                out.writeInt(0);
5390            }
5391            if (mFlashlightTurnedOnTimer != null) {
5392                out.writeInt(1);
5393                mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5394            } else {
5395                out.writeInt(0);
5396            }
5397            if (mCameraTurnedOnTimer != null) {
5398                out.writeInt(1);
5399                mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5400            } else {
5401                out.writeInt(0);
5402            }
5403            if (mForegroundActivityTimer != null) {
5404                out.writeInt(1);
5405                mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
5406            } else {
5407                out.writeInt(0);
5408            }
5409            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
5410                if (mProcessStateTimer[i] != null) {
5411                    out.writeInt(1);
5412                    mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
5413                } else {
5414                    out.writeInt(0);
5415                }
5416            }
5417            if (mVibratorOnTimer != null) {
5418                out.writeInt(1);
5419                mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
5420            } else {
5421                out.writeInt(0);
5422            }
5423            if (mUserActivityCounters != null) {
5424                out.writeInt(1);
5425                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5426                    mUserActivityCounters[i].writeToParcel(out);
5427                }
5428            } else {
5429                out.writeInt(0);
5430            }
5431            if (mNetworkByteActivityCounters != null) {
5432                out.writeInt(1);
5433                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5434                    mNetworkByteActivityCounters[i].writeToParcel(out);
5435                    mNetworkPacketActivityCounters[i].writeToParcel(out);
5436                }
5437                mMobileRadioActiveTime.writeToParcel(out);
5438                mMobileRadioActiveCount.writeToParcel(out);
5439            } else {
5440                out.writeInt(0);
5441            }
5442
5443            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5444                if (mWifiControllerTime[i] != null) {
5445                    out.writeInt(1);
5446                    mWifiControllerTime[i].writeToParcel(out);
5447                } else {
5448                    out.writeInt(0);
5449                }
5450            }
5451
5452            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5453                if (mBluetoothControllerTime[i] != null) {
5454                    out.writeInt(1);
5455                    mBluetoothControllerTime[i].writeToParcel(out);
5456                } else {
5457                    out.writeInt(0);
5458                }
5459            }
5460
5461            mUserCpuTime.writeToParcel(out);
5462            mSystemCpuTime.writeToParcel(out);
5463            mCpuPower.writeToParcel(out);
5464
5465            out.writeInt(mSpeedBins.length);
5466            for (int i = 0; i < mSpeedBins.length; i++) {
5467                LongSamplingCounter c = mSpeedBins[i];
5468                if (c != null) {
5469                    out.writeInt(1);
5470                    c.writeToParcel(out);
5471                } else {
5472                    out.writeInt(0);
5473                }
5474            }
5475        }
5476
5477        void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
5478            int numWakelocks = in.readInt();
5479            mWakelockStats.clear();
5480            for (int j = 0; j < numWakelocks; j++) {
5481                String wakelockName = in.readString();
5482                Uid.Wakelock wakelock = new Wakelock();
5483                wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
5484                mWakelockStats.add(wakelockName, wakelock);
5485            }
5486
5487            int numSyncs = in.readInt();
5488            mSyncStats.clear();
5489            for (int j = 0; j < numSyncs; j++) {
5490                String syncName = in.readString();
5491                if (in.readInt() != 0) {
5492                    mSyncStats.add(syncName,
5493                            new StopwatchTimer(Uid.this, SYNC, null, timeBase, in));
5494                }
5495            }
5496
5497            int numJobs = in.readInt();
5498            mJobStats.clear();
5499            for (int j = 0; j < numJobs; j++) {
5500                String jobName = in.readString();
5501                if (in.readInt() != 0) {
5502                    mJobStats.add(jobName, new StopwatchTimer(Uid.this, JOB, null, timeBase, in));
5503                }
5504            }
5505
5506            int numSensors = in.readInt();
5507            mSensorStats.clear();
5508            for (int k = 0; k < numSensors; k++) {
5509                int sensorNumber = in.readInt();
5510                Uid.Sensor sensor = new Sensor(sensorNumber);
5511                sensor.readFromParcelLocked(mOnBatteryTimeBase, in);
5512                mSensorStats.put(sensorNumber, sensor);
5513            }
5514
5515            int numProcs = in.readInt();
5516            mProcessStats.clear();
5517            for (int k = 0; k < numProcs; k++) {
5518                String processName = in.readString();
5519                Uid.Proc proc = new Proc(processName);
5520                proc.readFromParcelLocked(in);
5521                mProcessStats.put(processName, proc);
5522            }
5523
5524            int numPkgs = in.readInt();
5525            mPackageStats.clear();
5526            for (int l = 0; l < numPkgs; l++) {
5527                String packageName = in.readString();
5528                Uid.Pkg pkg = new Pkg();
5529                pkg.readFromParcelLocked(in);
5530                mPackageStats.put(packageName, pkg);
5531            }
5532
5533            mWifiRunning = false;
5534            if (in.readInt() != 0) {
5535                mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
5536                        mWifiRunningTimers, mOnBatteryTimeBase, in);
5537            } else {
5538                mWifiRunningTimer = null;
5539            }
5540            mFullWifiLockOut = false;
5541            if (in.readInt() != 0) {
5542                mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
5543                        mFullWifiLockTimers, mOnBatteryTimeBase, in);
5544            } else {
5545                mFullWifiLockTimer = null;
5546            }
5547            mWifiScanStarted = false;
5548            if (in.readInt() != 0) {
5549                mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
5550                        mWifiScanTimers, mOnBatteryTimeBase, in);
5551            } else {
5552                mWifiScanTimer = null;
5553            }
5554            mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
5555            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5556                if (in.readInt() != 0) {
5557                    makeWifiBatchedScanBin(i, in);
5558                } else {
5559                    mWifiBatchedScanTimer[i] = null;
5560                }
5561            }
5562            mWifiMulticastEnabled = false;
5563            if (in.readInt() != 0) {
5564                mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
5565                        mWifiMulticastTimers, mOnBatteryTimeBase, in);
5566            } else {
5567                mWifiMulticastTimer = null;
5568            }
5569            if (in.readInt() != 0) {
5570                mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
5571                        mAudioTurnedOnTimers, mOnBatteryTimeBase, in);
5572            } else {
5573                mAudioTurnedOnTimer = null;
5574            }
5575            if (in.readInt() != 0) {
5576                mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
5577                        mVideoTurnedOnTimers, mOnBatteryTimeBase, in);
5578            } else {
5579                mVideoTurnedOnTimer = null;
5580            }
5581            if (in.readInt() != 0) {
5582                mFlashlightTurnedOnTimer = new StopwatchTimer(Uid.this, FLASHLIGHT_TURNED_ON,
5583                        mFlashlightTurnedOnTimers, mOnBatteryTimeBase, in);
5584            } else {
5585                mFlashlightTurnedOnTimer = null;
5586            }
5587            if (in.readInt() != 0) {
5588                mCameraTurnedOnTimer = new StopwatchTimer(Uid.this, CAMERA_TURNED_ON,
5589                        mCameraTurnedOnTimers, mOnBatteryTimeBase, in);
5590            } else {
5591                mCameraTurnedOnTimer = null;
5592            }
5593            if (in.readInt() != 0) {
5594                mForegroundActivityTimer = new StopwatchTimer(
5595                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase, in);
5596            } else {
5597                mForegroundActivityTimer = null;
5598            }
5599            mProcessState = PROCESS_STATE_NONE;
5600            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
5601                if (in.readInt() != 0) {
5602                    makeProcessState(i, in);
5603                } else {
5604                    mProcessStateTimer[i] = null;
5605                }
5606            }
5607            if (in.readInt() != 0) {
5608                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase, in);
5609            } else {
5610                mVibratorOnTimer = null;
5611            }
5612            if (in.readInt() != 0) {
5613                mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
5614                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5615                    mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase, in);
5616                }
5617            } else {
5618                mUserActivityCounters = null;
5619            }
5620            if (in.readInt() != 0) {
5621                mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5622                mNetworkPacketActivityCounters
5623                        = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5624                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5625                    mNetworkByteActivityCounters[i]
5626                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
5627                    mNetworkPacketActivityCounters[i]
5628                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
5629                }
5630                mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
5631                mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
5632            } else {
5633                mNetworkByteActivityCounters = null;
5634                mNetworkPacketActivityCounters = null;
5635            }
5636
5637            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5638                if (in.readInt() != 0) {
5639                    mWifiControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
5640                } else {
5641                    mWifiControllerTime[i] = null;
5642                }
5643            }
5644
5645            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5646                if (in.readInt() != 0) {
5647                    mBluetoothControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
5648                } else {
5649                    mBluetoothControllerTime[i] = null;
5650                }
5651            }
5652
5653            mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
5654            mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
5655            mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in);
5656
5657            int bins = in.readInt();
5658            int steps = getCpuSpeedSteps();
5659            mSpeedBins = new LongSamplingCounter[bins >= steps ? bins : steps];
5660            for (int i = 0; i < bins; i++) {
5661                if (in.readInt() != 0) {
5662                    mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
5663                }
5664            }
5665        }
5666
5667        /**
5668         * The statistics associated with a particular wake lock.
5669         */
5670        public final class Wakelock extends BatteryStats.Uid.Wakelock {
5671            /**
5672             * How long (in ms) this uid has been keeping the device partially awake.
5673             */
5674            StopwatchTimer mTimerPartial;
5675
5676            /**
5677             * How long (in ms) this uid has been keeping the device fully awake.
5678             */
5679            StopwatchTimer mTimerFull;
5680
5681            /**
5682             * How long (in ms) this uid has had a window keeping the device awake.
5683             */
5684            StopwatchTimer mTimerWindow;
5685
5686            /**
5687             * How long (in ms) this uid has had a draw wake lock.
5688             */
5689            StopwatchTimer mTimerDraw;
5690
5691            /**
5692             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
5693             * proper timer pool from the given BatteryStatsImpl object.
5694             *
5695             * @param in the Parcel to be read from.
5696             * return a new Timer, or null.
5697             */
5698            private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
5699                    TimeBase timeBase, Parcel in) {
5700                if (in.readInt() == 0) {
5701                    return null;
5702                }
5703
5704                return new StopwatchTimer(Uid.this, type, pool, timeBase, in);
5705            }
5706
5707            boolean reset() {
5708                boolean wlactive = false;
5709                if (mTimerFull != null) {
5710                    wlactive |= !mTimerFull.reset(false);
5711                }
5712                if (mTimerPartial != null) {
5713                    wlactive |= !mTimerPartial.reset(false);
5714                }
5715                if (mTimerWindow != null) {
5716                    wlactive |= !mTimerWindow.reset(false);
5717                }
5718                if (mTimerDraw != null) {
5719                    wlactive |= !mTimerDraw.reset(false);
5720                }
5721                if (!wlactive) {
5722                    if (mTimerFull != null) {
5723                        mTimerFull.detach();
5724                        mTimerFull = null;
5725                    }
5726                    if (mTimerPartial != null) {
5727                        mTimerPartial.detach();
5728                        mTimerPartial = null;
5729                    }
5730                    if (mTimerWindow != null) {
5731                        mTimerWindow.detach();
5732                        mTimerWindow = null;
5733                    }
5734                    if (mTimerDraw != null) {
5735                        mTimerDraw.detach();
5736                        mTimerDraw = null;
5737                    }
5738                }
5739                return !wlactive;
5740            }
5741
5742            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
5743                mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
5744                        mPartialTimers, screenOffTimeBase, in);
5745                mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, mFullTimers, timeBase, in);
5746                mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, mWindowTimers, timeBase, in);
5747                mTimerDraw = readTimerFromParcel(WAKE_TYPE_DRAW, mDrawTimers, timeBase, in);
5748            }
5749
5750            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
5751                Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
5752                Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
5753                Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
5754                Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
5755            }
5756
5757            @Override
5758            public Timer getWakeTime(int type) {
5759                switch (type) {
5760                case WAKE_TYPE_FULL: return mTimerFull;
5761                case WAKE_TYPE_PARTIAL: return mTimerPartial;
5762                case WAKE_TYPE_WINDOW: return mTimerWindow;
5763                case WAKE_TYPE_DRAW: return mTimerDraw;
5764                default: throw new IllegalArgumentException("type = " + type);
5765                }
5766            }
5767
5768            public StopwatchTimer getStopwatchTimer(int type) {
5769                StopwatchTimer t;
5770                switch (type) {
5771                    case WAKE_TYPE_PARTIAL:
5772                        t = mTimerPartial;
5773                        if (t == null) {
5774                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
5775                                    mPartialTimers, mOnBatteryScreenOffTimeBase);
5776                            mTimerPartial = t;
5777                        }
5778                        return t;
5779                    case WAKE_TYPE_FULL:
5780                        t = mTimerFull;
5781                        if (t == null) {
5782                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
5783                                    mFullTimers, mOnBatteryTimeBase);
5784                            mTimerFull = t;
5785                        }
5786                        return t;
5787                    case WAKE_TYPE_WINDOW:
5788                        t = mTimerWindow;
5789                        if (t == null) {
5790                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
5791                                    mWindowTimers, mOnBatteryTimeBase);
5792                            mTimerWindow = t;
5793                        }
5794                        return t;
5795                    case WAKE_TYPE_DRAW:
5796                        t = mTimerDraw;
5797                        if (t == null) {
5798                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_DRAW,
5799                                    mDrawTimers, mOnBatteryTimeBase);
5800                            mTimerDraw = t;
5801                        }
5802                        return t;
5803                    default:
5804                        throw new IllegalArgumentException("type=" + type);
5805                }
5806            }
5807        }
5808
5809        public final class Sensor extends BatteryStats.Uid.Sensor {
5810            final int mHandle;
5811            StopwatchTimer mTimer;
5812
5813            public Sensor(int handle) {
5814                mHandle = handle;
5815            }
5816
5817            private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) {
5818                if (in.readInt() == 0) {
5819                    return null;
5820                }
5821
5822                ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
5823                if (pool == null) {
5824                    pool = new ArrayList<StopwatchTimer>();
5825                    mSensorTimers.put(mHandle, pool);
5826                }
5827                return new StopwatchTimer(Uid.this, 0, pool, timeBase, in);
5828            }
5829
5830            boolean reset() {
5831                if (mTimer.reset(true)) {
5832                    mTimer = null;
5833                    return true;
5834                }
5835                return false;
5836            }
5837
5838            void readFromParcelLocked(TimeBase timeBase, Parcel in) {
5839                mTimer = readTimerFromParcel(timeBase, in);
5840            }
5841
5842            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
5843                Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
5844            }
5845
5846            @Override
5847            public Timer getSensorTime() {
5848                return mTimer;
5849            }
5850
5851            @Override
5852            public int getHandle() {
5853                return mHandle;
5854            }
5855        }
5856
5857        /**
5858         * The statistics associated with a particular process.
5859         */
5860        public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
5861            /**
5862             * The name of this process.
5863             */
5864            final String mName;
5865
5866            /**
5867             * Remains true until removed from the stats.
5868             */
5869            boolean mActive = true;
5870
5871            /**
5872             * Total time (in ms) spent executing in user code.
5873             */
5874            long mUserTime;
5875
5876            /**
5877             * Total time (in ms) spent executing in kernel code.
5878             */
5879            long mSystemTime;
5880
5881            /**
5882             * Amount of time (in ms) the process was running in the foreground.
5883             */
5884            long mForegroundTime;
5885
5886            /**
5887             * Number of times the process has been started.
5888             */
5889            int mStarts;
5890
5891            /**
5892             * Number of times the process has crashed.
5893             */
5894            int mNumCrashes;
5895
5896            /**
5897             * Number of times the process has had an ANR.
5898             */
5899            int mNumAnrs;
5900
5901            /**
5902             * The amount of user time loaded from a previous save.
5903             */
5904            long mLoadedUserTime;
5905
5906            /**
5907             * The amount of system time loaded from a previous save.
5908             */
5909            long mLoadedSystemTime;
5910
5911            /**
5912             * The amount of foreground time loaded from a previous save.
5913             */
5914            long mLoadedForegroundTime;
5915
5916            /**
5917             * The number of times the process has started from a previous save.
5918             */
5919            int mLoadedStarts;
5920
5921            /**
5922             * Number of times the process has crashed from a previous save.
5923             */
5924            int mLoadedNumCrashes;
5925
5926            /**
5927             * Number of times the process has had an ANR from a previous save.
5928             */
5929            int mLoadedNumAnrs;
5930
5931            /**
5932             * The amount of user time when last unplugged.
5933             */
5934            long mUnpluggedUserTime;
5935
5936            /**
5937             * The amount of system time when last unplugged.
5938             */
5939            long mUnpluggedSystemTime;
5940
5941            /**
5942             * The amount of foreground time since unplugged.
5943             */
5944            long mUnpluggedForegroundTime;
5945
5946            /**
5947             * The number of times the process has started before unplugged.
5948             */
5949            int mUnpluggedStarts;
5950
5951            /**
5952             * Number of times the process has crashed before unplugged.
5953             */
5954            int mUnpluggedNumCrashes;
5955
5956            /**
5957             * Number of times the process has had an ANR before unplugged.
5958             */
5959            int mUnpluggedNumAnrs;
5960
5961            /**
5962             * Current process state.
5963             */
5964            int mProcessState = PROCESS_STATE_NONE;
5965
5966            ArrayList<ExcessivePower> mExcessivePower;
5967
5968            Proc(String name) {
5969                mName = name;
5970                mOnBatteryTimeBase.add(this);
5971            }
5972
5973            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
5974                mUnpluggedUserTime = mUserTime;
5975                mUnpluggedSystemTime = mSystemTime;
5976                mUnpluggedForegroundTime = mForegroundTime;
5977                mUnpluggedStarts = mStarts;
5978                mUnpluggedNumCrashes = mNumCrashes;
5979                mUnpluggedNumAnrs = mNumAnrs;
5980            }
5981
5982            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
5983            }
5984
5985            void reset() {
5986                mUserTime = mSystemTime = mForegroundTime = 0;
5987                mStarts = mNumCrashes = mNumAnrs = 0;
5988                mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0;
5989                mLoadedStarts = mLoadedNumCrashes = mLoadedNumAnrs = 0;
5990                mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0;
5991                mUnpluggedStarts = mUnpluggedNumCrashes = mUnpluggedNumAnrs = 0;
5992                mExcessivePower = null;
5993            }
5994
5995            void detach() {
5996                mActive = false;
5997                mOnBatteryTimeBase.remove(this);
5998            }
5999
6000            public int countExcessivePowers() {
6001                return mExcessivePower != null ? mExcessivePower.size() : 0;
6002            }
6003
6004            public ExcessivePower getExcessivePower(int i) {
6005                if (mExcessivePower != null) {
6006                    return mExcessivePower.get(i);
6007                }
6008                return null;
6009            }
6010
6011            public void addExcessiveWake(long overTime, long usedTime) {
6012                if (mExcessivePower == null) {
6013                    mExcessivePower = new ArrayList<ExcessivePower>();
6014                }
6015                ExcessivePower ew = new ExcessivePower();
6016                ew.type = ExcessivePower.TYPE_WAKE;
6017                ew.overTime = overTime;
6018                ew.usedTime = usedTime;
6019                mExcessivePower.add(ew);
6020            }
6021
6022            public void addExcessiveCpu(long overTime, long usedTime) {
6023                if (mExcessivePower == null) {
6024                    mExcessivePower = new ArrayList<ExcessivePower>();
6025                }
6026                ExcessivePower ew = new ExcessivePower();
6027                ew.type = ExcessivePower.TYPE_CPU;
6028                ew.overTime = overTime;
6029                ew.usedTime = usedTime;
6030                mExcessivePower.add(ew);
6031            }
6032
6033            void writeExcessivePowerToParcelLocked(Parcel out) {
6034                if (mExcessivePower == null) {
6035                    out.writeInt(0);
6036                    return;
6037                }
6038
6039                final int N = mExcessivePower.size();
6040                out.writeInt(N);
6041                for (int i=0; i<N; i++) {
6042                    ExcessivePower ew = mExcessivePower.get(i);
6043                    out.writeInt(ew.type);
6044                    out.writeLong(ew.overTime);
6045                    out.writeLong(ew.usedTime);
6046                }
6047            }
6048
6049            void readExcessivePowerFromParcelLocked(Parcel in) {
6050                final int N = in.readInt();
6051                if (N == 0) {
6052                    mExcessivePower = null;
6053                    return;
6054                }
6055
6056                if (N > 10000) {
6057                    throw new ParcelFormatException(
6058                            "File corrupt: too many excessive power entries " + N);
6059                }
6060
6061                mExcessivePower = new ArrayList<>();
6062                for (int i=0; i<N; i++) {
6063                    ExcessivePower ew = new ExcessivePower();
6064                    ew.type = in.readInt();
6065                    ew.overTime = in.readLong();
6066                    ew.usedTime = in.readLong();
6067                    mExcessivePower.add(ew);
6068                }
6069            }
6070
6071            void writeToParcelLocked(Parcel out) {
6072                out.writeLong(mUserTime);
6073                out.writeLong(mSystemTime);
6074                out.writeLong(mForegroundTime);
6075                out.writeInt(mStarts);
6076                out.writeInt(mNumCrashes);
6077                out.writeInt(mNumAnrs);
6078                out.writeLong(mLoadedUserTime);
6079                out.writeLong(mLoadedSystemTime);
6080                out.writeLong(mLoadedForegroundTime);
6081                out.writeInt(mLoadedStarts);
6082                out.writeInt(mLoadedNumCrashes);
6083                out.writeInt(mLoadedNumAnrs);
6084                out.writeLong(mUnpluggedUserTime);
6085                out.writeLong(mUnpluggedSystemTime);
6086                out.writeLong(mUnpluggedForegroundTime);
6087                out.writeInt(mUnpluggedStarts);
6088                out.writeInt(mUnpluggedNumCrashes);
6089                out.writeInt(mUnpluggedNumAnrs);
6090                writeExcessivePowerToParcelLocked(out);
6091            }
6092
6093            void readFromParcelLocked(Parcel in) {
6094                mUserTime = in.readLong();
6095                mSystemTime = in.readLong();
6096                mForegroundTime = in.readLong();
6097                mStarts = in.readInt();
6098                mNumCrashes = in.readInt();
6099                mNumAnrs = in.readInt();
6100                mLoadedUserTime = in.readLong();
6101                mLoadedSystemTime = in.readLong();
6102                mLoadedForegroundTime = in.readLong();
6103                mLoadedStarts = in.readInt();
6104                mLoadedNumCrashes = in.readInt();
6105                mLoadedNumAnrs = in.readInt();
6106                mUnpluggedUserTime = in.readLong();
6107                mUnpluggedSystemTime = in.readLong();
6108                mUnpluggedForegroundTime = in.readLong();
6109                mUnpluggedStarts = in.readInt();
6110                mUnpluggedNumCrashes = in.readInt();
6111                mUnpluggedNumAnrs = in.readInt();
6112                readExcessivePowerFromParcelLocked(in);
6113            }
6114
6115            public void addCpuTimeLocked(int utime, int stime) {
6116                mUserTime += utime;
6117                mSystemTime += stime;
6118            }
6119
6120            public void addForegroundTimeLocked(long ttime) {
6121                mForegroundTime += ttime;
6122            }
6123
6124            public void incStartsLocked() {
6125                mStarts++;
6126            }
6127
6128            public void incNumCrashesLocked() {
6129                mNumCrashes++;
6130            }
6131
6132            public void incNumAnrsLocked() {
6133                mNumAnrs++;
6134            }
6135
6136            @Override
6137            public boolean isActive() {
6138                return mActive;
6139            }
6140
6141            @Override
6142            public long getUserTime(int which) {
6143                long val = mUserTime;
6144                if (which == STATS_CURRENT) {
6145                    val -= mLoadedUserTime;
6146                } else if (which == STATS_SINCE_UNPLUGGED) {
6147                    val -= mUnpluggedUserTime;
6148                }
6149                return val;
6150            }
6151
6152            @Override
6153            public long getSystemTime(int which) {
6154                long val = mSystemTime;
6155                if (which == STATS_CURRENT) {
6156                    val -= mLoadedSystemTime;
6157                } else if (which == STATS_SINCE_UNPLUGGED) {
6158                    val -= mUnpluggedSystemTime;
6159                }
6160                return val;
6161            }
6162
6163            @Override
6164            public long getForegroundTime(int which) {
6165                long val = mForegroundTime;
6166                if (which == STATS_CURRENT) {
6167                    val -= mLoadedForegroundTime;
6168                } else if (which == STATS_SINCE_UNPLUGGED) {
6169                    val -= mUnpluggedForegroundTime;
6170                }
6171                return val;
6172            }
6173
6174            @Override
6175            public int getStarts(int which) {
6176                int val = mStarts;
6177                if (which == STATS_CURRENT) {
6178                    val -= mLoadedStarts;
6179                } else if (which == STATS_SINCE_UNPLUGGED) {
6180                    val -= mUnpluggedStarts;
6181                }
6182                return val;
6183            }
6184
6185            @Override
6186            public int getNumCrashes(int which) {
6187                int val = mNumCrashes;
6188                if (which == STATS_CURRENT) {
6189                    val -= mLoadedNumCrashes;
6190                } else if (which == STATS_SINCE_UNPLUGGED) {
6191                    val -= mUnpluggedNumCrashes;
6192                }
6193                return val;
6194            }
6195
6196            @Override
6197            public int getNumAnrs(int which) {
6198                int val = mNumAnrs;
6199                if (which == STATS_CURRENT) {
6200                    val -= mLoadedNumAnrs;
6201                } else if (which == STATS_SINCE_UNPLUGGED) {
6202                    val -= mUnpluggedNumAnrs;
6203                }
6204                return val;
6205            }
6206        }
6207
6208        /**
6209         * The statistics associated with a particular package.
6210         */
6211        public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
6212            /**
6213             * Number of times wakeup alarms have occurred for this app.
6214             */
6215            ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
6216
6217            /**
6218             * The statics we have collected for this package's services.
6219             */
6220            final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
6221
6222            Pkg() {
6223                mOnBatteryScreenOffTimeBase.add(this);
6224            }
6225
6226            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
6227            }
6228
6229            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
6230            }
6231
6232            void detach() {
6233                mOnBatteryScreenOffTimeBase.remove(this);
6234            }
6235
6236            void readFromParcelLocked(Parcel in) {
6237                int numWA = in.readInt();
6238                mWakeupAlarms.clear();
6239                for (int i=0; i<numWA; i++) {
6240                    String tag = in.readString();
6241                    mWakeupAlarms.put(tag, new Counter(mOnBatteryTimeBase, in));
6242                }
6243
6244                int numServs = in.readInt();
6245                mServiceStats.clear();
6246                for (int m = 0; m < numServs; m++) {
6247                    String serviceName = in.readString();
6248                    Uid.Pkg.Serv serv = new Serv();
6249                    mServiceStats.put(serviceName, serv);
6250
6251                    serv.readFromParcelLocked(in);
6252                }
6253            }
6254
6255            void writeToParcelLocked(Parcel out) {
6256                int numWA = mWakeupAlarms.size();
6257                out.writeInt(numWA);
6258                for (int i=0; i<numWA; i++) {
6259                    out.writeString(mWakeupAlarms.keyAt(i));
6260                    mWakeupAlarms.valueAt(i).writeToParcel(out);
6261                }
6262
6263                final int NS = mServiceStats.size();
6264                out.writeInt(NS);
6265                for (int i=0; i<NS; i++) {
6266                    out.writeString(mServiceStats.keyAt(i));
6267                    Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
6268                    serv.writeToParcelLocked(out);
6269                }
6270            }
6271
6272            @Override
6273            public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
6274                return mWakeupAlarms;
6275            }
6276
6277            public void noteWakeupAlarmLocked(String tag) {
6278                Counter c = mWakeupAlarms.get(tag);
6279                if (c == null) {
6280                    c = new Counter(mOnBatteryTimeBase);
6281                    mWakeupAlarms.put(tag, c);
6282                }
6283                c.stepAtomic();
6284            }
6285
6286            @Override
6287            public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
6288                return mServiceStats;
6289            }
6290
6291            /**
6292             * The statistics associated with a particular service.
6293             */
6294            public final class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
6295                /**
6296                 * Total time (ms in battery uptime) the service has been left started.
6297                 */
6298                long mStartTime;
6299
6300                /**
6301                 * If service has been started and not yet stopped, this is
6302                 * when it was started.
6303                 */
6304                long mRunningSince;
6305
6306                /**
6307                 * True if we are currently running.
6308                 */
6309                boolean mRunning;
6310
6311                /**
6312                 * Total number of times startService() has been called.
6313                 */
6314                int mStarts;
6315
6316                /**
6317                 * Total time (ms in battery uptime) the service has been left launched.
6318                 */
6319                long mLaunchedTime;
6320
6321                /**
6322                 * If service has been launched and not yet exited, this is
6323                 * when it was launched (ms in battery uptime).
6324                 */
6325                long mLaunchedSince;
6326
6327                /**
6328                 * True if we are currently launched.
6329                 */
6330                boolean mLaunched;
6331
6332                /**
6333                 * Total number times the service has been launched.
6334                 */
6335                int mLaunches;
6336
6337                /**
6338                 * The amount of time spent started loaded from a previous save
6339                 * (ms in battery uptime).
6340                 */
6341                long mLoadedStartTime;
6342
6343                /**
6344                 * The number of starts loaded from a previous save.
6345                 */
6346                int mLoadedStarts;
6347
6348                /**
6349                 * The number of launches loaded from a previous save.
6350                 */
6351                int mLoadedLaunches;
6352
6353                /**
6354                 * The amount of time spent started as of the last run (ms
6355                 * in battery uptime).
6356                 */
6357                long mLastStartTime;
6358
6359                /**
6360                 * The number of starts as of the last run.
6361                 */
6362                int mLastStarts;
6363
6364                /**
6365                 * The number of launches as of the last run.
6366                 */
6367                int mLastLaunches;
6368
6369                /**
6370                 * The amount of time spent started when last unplugged (ms
6371                 * in battery uptime).
6372                 */
6373                long mUnpluggedStartTime;
6374
6375                /**
6376                 * The number of starts when last unplugged.
6377                 */
6378                int mUnpluggedStarts;
6379
6380                /**
6381                 * The number of launches when last unplugged.
6382                 */
6383                int mUnpluggedLaunches;
6384
6385                Serv() {
6386                    mOnBatteryTimeBase.add(this);
6387                }
6388
6389                public void onTimeStarted(long elapsedRealtime, long baseUptime,
6390                        long baseRealtime) {
6391                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
6392                    mUnpluggedStarts = mStarts;
6393                    mUnpluggedLaunches = mLaunches;
6394                }
6395
6396                public void onTimeStopped(long elapsedRealtime, long baseUptime,
6397                        long baseRealtime) {
6398                }
6399
6400                void detach() {
6401                    mOnBatteryTimeBase.remove(this);
6402                }
6403
6404                void readFromParcelLocked(Parcel in) {
6405                    mStartTime = in.readLong();
6406                    mRunningSince = in.readLong();
6407                    mRunning = in.readInt() != 0;
6408                    mStarts = in.readInt();
6409                    mLaunchedTime = in.readLong();
6410                    mLaunchedSince = in.readLong();
6411                    mLaunched = in.readInt() != 0;
6412                    mLaunches = in.readInt();
6413                    mLoadedStartTime = in.readLong();
6414                    mLoadedStarts = in.readInt();
6415                    mLoadedLaunches = in.readInt();
6416                    mLastStartTime = 0;
6417                    mLastStarts = 0;
6418                    mLastLaunches = 0;
6419                    mUnpluggedStartTime = in.readLong();
6420                    mUnpluggedStarts = in.readInt();
6421                    mUnpluggedLaunches = in.readInt();
6422                }
6423
6424                void writeToParcelLocked(Parcel out) {
6425                    out.writeLong(mStartTime);
6426                    out.writeLong(mRunningSince);
6427                    out.writeInt(mRunning ? 1 : 0);
6428                    out.writeInt(mStarts);
6429                    out.writeLong(mLaunchedTime);
6430                    out.writeLong(mLaunchedSince);
6431                    out.writeInt(mLaunched ? 1 : 0);
6432                    out.writeInt(mLaunches);
6433                    out.writeLong(mLoadedStartTime);
6434                    out.writeInt(mLoadedStarts);
6435                    out.writeInt(mLoadedLaunches);
6436                    out.writeLong(mUnpluggedStartTime);
6437                    out.writeInt(mUnpluggedStarts);
6438                    out.writeInt(mUnpluggedLaunches);
6439                }
6440
6441                long getLaunchTimeToNowLocked(long batteryUptime) {
6442                    if (!mLaunched) return mLaunchedTime;
6443                    return mLaunchedTime + batteryUptime - mLaunchedSince;
6444                }
6445
6446                long getStartTimeToNowLocked(long batteryUptime) {
6447                    if (!mRunning) return mStartTime;
6448                    return mStartTime + batteryUptime - mRunningSince;
6449                }
6450
6451                public void startLaunchedLocked() {
6452                    if (!mLaunched) {
6453                        mLaunches++;
6454                        mLaunchedSince = getBatteryUptimeLocked();
6455                        mLaunched = true;
6456                    }
6457                }
6458
6459                public void stopLaunchedLocked() {
6460                    if (mLaunched) {
6461                        long time = getBatteryUptimeLocked() - mLaunchedSince;
6462                        if (time > 0) {
6463                            mLaunchedTime += time;
6464                        } else {
6465                            mLaunches--;
6466                        }
6467                        mLaunched = false;
6468                    }
6469                }
6470
6471                public void startRunningLocked() {
6472                    if (!mRunning) {
6473                        mStarts++;
6474                        mRunningSince = getBatteryUptimeLocked();
6475                        mRunning = true;
6476                    }
6477                }
6478
6479                public void stopRunningLocked() {
6480                    if (mRunning) {
6481                        long time = getBatteryUptimeLocked() - mRunningSince;
6482                        if (time > 0) {
6483                            mStartTime += time;
6484                        } else {
6485                            mStarts--;
6486                        }
6487                        mRunning = false;
6488                    }
6489                }
6490
6491                public BatteryStatsImpl getBatteryStats() {
6492                    return BatteryStatsImpl.this;
6493                }
6494
6495                @Override
6496                public int getLaunches(int which) {
6497                    int val = mLaunches;
6498                    if (which == STATS_CURRENT) {
6499                        val -= mLoadedLaunches;
6500                    } else if (which == STATS_SINCE_UNPLUGGED) {
6501                        val -= mUnpluggedLaunches;
6502                    }
6503                    return val;
6504                }
6505
6506                @Override
6507                public long getStartTime(long now, int which) {
6508                    long val = getStartTimeToNowLocked(now);
6509                    if (which == STATS_CURRENT) {
6510                        val -= mLoadedStartTime;
6511                    } else if (which == STATS_SINCE_UNPLUGGED) {
6512                        val -= mUnpluggedStartTime;
6513                    }
6514                    return val;
6515                }
6516
6517                @Override
6518                public int getStarts(int which) {
6519                    int val = mStarts;
6520                    if (which == STATS_CURRENT) {
6521                        val -= mLoadedStarts;
6522                    } else if (which == STATS_SINCE_UNPLUGGED) {
6523                        val -= mUnpluggedStarts;
6524                    }
6525
6526                    return val;
6527                }
6528            }
6529
6530            final Serv newServiceStatsLocked() {
6531                return new Serv();
6532            }
6533        }
6534
6535        /**
6536         * Retrieve the statistics object for a particular process, creating
6537         * if needed.
6538         */
6539        public Proc getProcessStatsLocked(String name) {
6540            Proc ps = mProcessStats.get(name);
6541            if (ps == null) {
6542                ps = new Proc(name);
6543                mProcessStats.put(name, ps);
6544            }
6545
6546            return ps;
6547        }
6548
6549        public void updateProcessStateLocked(String procName, int state, long elapsedRealtimeMs) {
6550            int procState;
6551            if (state <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
6552                procState = PROCESS_STATE_FOREGROUND;
6553            } else if (state <= ActivityManager.PROCESS_STATE_RECEIVER) {
6554                procState = PROCESS_STATE_ACTIVE;
6555            } else {
6556                procState = PROCESS_STATE_RUNNING;
6557            }
6558            updateRealProcessStateLocked(procName, procState, elapsedRealtimeMs);
6559        }
6560
6561        public void updateRealProcessStateLocked(String procName, int procState,
6562                long elapsedRealtimeMs) {
6563            Proc proc = getProcessStatsLocked(procName);
6564            if (proc.mProcessState != procState) {
6565                boolean changed;
6566                if (procState < proc.mProcessState) {
6567                    // Has this process become more important?  If so,
6568                    // we may need to change the uid if the currrent uid proc state
6569                    // is not as important as what we are now setting.
6570                    changed = mProcessState > procState;
6571                } else {
6572                    // Has this process become less important?  If so,
6573                    // we may need to change the uid if the current uid proc state
6574                    // is the same importance as the old setting.
6575                    changed = mProcessState == proc.mProcessState;
6576                }
6577                proc.mProcessState = procState;
6578                if (changed) {
6579                    // uid's state may have changed; compute what the new state should be.
6580                    int uidProcState = PROCESS_STATE_NONE;
6581                    for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
6582                        proc = mProcessStats.valueAt(ip);
6583                        if (proc.mProcessState < uidProcState) {
6584                            uidProcState = proc.mProcessState;
6585                        }
6586                    }
6587                    updateUidProcessStateLocked(uidProcState, elapsedRealtimeMs);
6588                }
6589            }
6590        }
6591
6592        public SparseArray<? extends Pid> getPidStats() {
6593            return mPids;
6594        }
6595
6596        public Pid getPidStatsLocked(int pid) {
6597            Pid p = mPids.get(pid);
6598            if (p == null) {
6599                p = new Pid();
6600                mPids.put(pid, p);
6601            }
6602            return p;
6603        }
6604
6605        /**
6606         * Retrieve the statistics object for a particular service, creating
6607         * if needed.
6608         */
6609        public Pkg getPackageStatsLocked(String name) {
6610            Pkg ps = mPackageStats.get(name);
6611            if (ps == null) {
6612                ps = new Pkg();
6613                mPackageStats.put(name, ps);
6614            }
6615
6616            return ps;
6617        }
6618
6619        /**
6620         * Retrieve the statistics object for a particular service, creating
6621         * if needed.
6622         */
6623        public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
6624            Pkg ps = getPackageStatsLocked(pkg);
6625            Pkg.Serv ss = ps.mServiceStats.get(serv);
6626            if (ss == null) {
6627                ss = ps.newServiceStatsLocked();
6628                ps.mServiceStats.put(serv, ss);
6629            }
6630
6631            return ss;
6632        }
6633
6634        public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
6635            StopwatchTimer timer = mSyncStats.instantiateObject();
6636            timer.readSummaryFromParcelLocked(in);
6637            mSyncStats.add(name, timer);
6638        }
6639
6640        public void readJobSummaryFromParcelLocked(String name, Parcel in) {
6641            StopwatchTimer timer = mJobStats.instantiateObject();
6642            timer.readSummaryFromParcelLocked(in);
6643            mJobStats.add(name, timer);
6644        }
6645
6646        public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
6647            Wakelock wl = new Wakelock();
6648            mWakelockStats.add(wlName, wl);
6649            if (in.readInt() != 0) {
6650                wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
6651            }
6652            if (in.readInt() != 0) {
6653                wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
6654            }
6655            if (in.readInt() != 0) {
6656                wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
6657            }
6658            if (in.readInt() != 0) {
6659                wl.getStopwatchTimer(WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
6660            }
6661        }
6662
6663        public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
6664            Sensor se = mSensorStats.get(sensor);
6665            if (se == null) {
6666                if (!create) {
6667                    return null;
6668                }
6669                se = new Sensor(sensor);
6670                mSensorStats.put(sensor, se);
6671            }
6672            StopwatchTimer t = se.mTimer;
6673            if (t != null) {
6674                return t;
6675            }
6676            ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
6677            if (timers == null) {
6678                timers = new ArrayList<StopwatchTimer>();
6679                mSensorTimers.put(sensor, timers);
6680            }
6681            t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mOnBatteryTimeBase);
6682            se.mTimer = t;
6683            return t;
6684        }
6685
6686        public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
6687            StopwatchTimer t = mSyncStats.startObject(name);
6688            if (t != null) {
6689                t.startRunningLocked(elapsedRealtimeMs);
6690            }
6691        }
6692
6693        public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
6694            StopwatchTimer t = mSyncStats.stopObject(name);
6695            if (t != null) {
6696                t.stopRunningLocked(elapsedRealtimeMs);
6697            }
6698        }
6699
6700        public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
6701            StopwatchTimer t = mJobStats.startObject(name);
6702            if (t != null) {
6703                t.startRunningLocked(elapsedRealtimeMs);
6704            }
6705        }
6706
6707        public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
6708            StopwatchTimer t = mJobStats.stopObject(name);
6709            if (t != null) {
6710                t.stopRunningLocked(elapsedRealtimeMs);
6711            }
6712        }
6713
6714        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
6715            Wakelock wl = mWakelockStats.startObject(name);
6716            if (wl != null) {
6717                wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
6718            }
6719            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
6720                Pid p = getPidStatsLocked(pid);
6721                if (p.mWakeNesting++ == 0) {
6722                    p.mWakeStartMs = elapsedRealtimeMs;
6723                }
6724            }
6725        }
6726
6727        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
6728            Wakelock wl = mWakelockStats.stopObject(name);
6729            if (wl != null) {
6730                wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
6731            }
6732            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
6733                Pid p = mPids.get(pid);
6734                if (p != null && p.mWakeNesting > 0) {
6735                    if (p.mWakeNesting-- == 1) {
6736                        p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
6737                        p.mWakeStartMs = 0;
6738                    }
6739                }
6740            }
6741        }
6742
6743        public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
6744            Proc p = getProcessStatsLocked(proc);
6745            if (p != null) {
6746                p.addExcessiveWake(overTime, usedTime);
6747            }
6748        }
6749
6750        public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
6751            Proc p = getProcessStatsLocked(proc);
6752            if (p != null) {
6753                p.addExcessiveCpu(overTime, usedTime);
6754            }
6755        }
6756
6757        public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
6758            StopwatchTimer t = getSensorTimerLocked(sensor, true);
6759            if (t != null) {
6760                t.startRunningLocked(elapsedRealtimeMs);
6761            }
6762        }
6763
6764        public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
6765            // Don't create a timer if one doesn't already exist
6766            StopwatchTimer t = getSensorTimerLocked(sensor, false);
6767            if (t != null) {
6768                t.stopRunningLocked(elapsedRealtimeMs);
6769            }
6770        }
6771
6772        public void noteStartGps(long elapsedRealtimeMs) {
6773            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
6774            if (t != null) {
6775                t.startRunningLocked(elapsedRealtimeMs);
6776            }
6777        }
6778
6779        public void noteStopGps(long elapsedRealtimeMs) {
6780            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
6781            if (t != null) {
6782                t.stopRunningLocked(elapsedRealtimeMs);
6783            }
6784        }
6785
6786        public BatteryStatsImpl getBatteryStats() {
6787            return BatteryStatsImpl.this;
6788        }
6789    }
6790
6791    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
6792        if (systemDir != null) {
6793            mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
6794                    new File(systemDir, "batterystats.bin.tmp"));
6795        } else {
6796            mFile = null;
6797        }
6798        mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
6799        mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
6800        mExternalSync = externalSync;
6801        mHandler = new MyHandler(handler.getLooper());
6802        mStartCount++;
6803        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
6804        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
6805            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
6806        }
6807        mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase);
6808        mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
6809        mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
6810        mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase);
6811        mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
6812        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
6813            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
6814                    mOnBatteryTimeBase);
6815        }
6816        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase);
6817        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
6818            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null,
6819                    mOnBatteryTimeBase);
6820        }
6821        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6822            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6823            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6824        }
6825        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
6826            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6827            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6828        }
6829        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
6830        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
6831        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
6832        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
6833        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
6834        mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase);
6835        mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase);
6836        for (int i=0; i<NUM_WIFI_STATES; i++) {
6837            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mOnBatteryTimeBase);
6838        }
6839        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
6840            mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i, null, mOnBatteryTimeBase);
6841        }
6842        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
6843            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i, null,
6844                    mOnBatteryTimeBase);
6845        }
6846        mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
6847        mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
6848        mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
6849        mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase);
6850        mOnBattery = mOnBatteryInternal = false;
6851        long uptime = SystemClock.uptimeMillis() * 1000;
6852        long realtime = SystemClock.elapsedRealtime() * 1000;
6853        initTimes(uptime, realtime);
6854        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
6855        mDischargeStartLevel = 0;
6856        mDischargeUnplugLevel = 0;
6857        mDischargePlugLevel = -1;
6858        mDischargeCurrentLevel = 0;
6859        mCurrentBatteryLevel = 0;
6860        initDischarge();
6861        clearHistoryLocked();
6862        updateDailyDeadlineLocked();
6863    }
6864
6865    public BatteryStatsImpl(Parcel p) {
6866        mFile = null;
6867        mCheckinFile = null;
6868        mDailyFile = null;
6869        mHandler = null;
6870        mExternalSync = null;
6871        clearHistoryLocked();
6872        readFromParcel(p);
6873    }
6874
6875    public void setPowerProfile(PowerProfile profile) {
6876        synchronized (this) {
6877            mPowerProfile = profile;
6878        }
6879    }
6880
6881    public void setCallback(BatteryCallback cb) {
6882        mCallback = cb;
6883    }
6884
6885    public void setNumSpeedSteps(int steps) {
6886        if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
6887    }
6888
6889    public void setRadioScanningTimeout(long timeout) {
6890        if (mPhoneSignalScanningTimer != null) {
6891            mPhoneSignalScanningTimer.setTimeout(timeout);
6892        }
6893    }
6894
6895    public void updateDailyDeadlineLocked() {
6896        // Get the current time.
6897        long currentTime = mDailyStartTime = System.currentTimeMillis();
6898        Calendar calDeadline = Calendar.getInstance();
6899        calDeadline.setTimeInMillis(currentTime);
6900
6901        // Move time up to the next day, ranging from 1am to 3pm.
6902        calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
6903        calDeadline.set(Calendar.MILLISECOND, 0);
6904        calDeadline.set(Calendar.SECOND, 0);
6905        calDeadline.set(Calendar.MINUTE, 0);
6906        calDeadline.set(Calendar.HOUR_OF_DAY, 1);
6907        mNextMinDailyDeadline = calDeadline.getTimeInMillis();
6908        calDeadline.set(Calendar.HOUR_OF_DAY, 3);
6909        mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
6910    }
6911
6912    public void recordDailyStatsIfNeededLocked(boolean settled) {
6913        long currentTime = System.currentTimeMillis();
6914        if (currentTime >= mNextMaxDailyDeadline) {
6915            recordDailyStatsLocked();
6916        } else if (settled && currentTime >= mNextMinDailyDeadline) {
6917            recordDailyStatsLocked();
6918        } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
6919            recordDailyStatsLocked();
6920        }
6921    }
6922
6923    public void recordDailyStatsLocked() {
6924        DailyItem item = new DailyItem();
6925        item.mStartTime = mDailyStartTime;
6926        item.mEndTime = System.currentTimeMillis();
6927        boolean hasData = false;
6928        if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
6929            hasData = true;
6930            item.mDischargeSteps = new LevelStepTracker(
6931                    mDailyDischargeStepTracker.mNumStepDurations,
6932                    mDailyDischargeStepTracker.mStepDurations);
6933        }
6934        if (mDailyChargeStepTracker.mNumStepDurations > 0) {
6935            hasData = true;
6936            item.mChargeSteps = new LevelStepTracker(
6937                    mDailyChargeStepTracker.mNumStepDurations,
6938                    mDailyChargeStepTracker.mStepDurations);
6939        }
6940        if (mDailyPackageChanges != null) {
6941            hasData = true;
6942            item.mPackageChanges = mDailyPackageChanges;
6943            mDailyPackageChanges = null;
6944        }
6945        mDailyDischargeStepTracker.init();
6946        mDailyChargeStepTracker.init();
6947        updateDailyDeadlineLocked();
6948
6949        if (hasData) {
6950            mDailyItems.add(item);
6951            while (mDailyItems.size() > MAX_DAILY_ITEMS) {
6952                mDailyItems.remove(0);
6953            }
6954            final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
6955            try {
6956                XmlSerializer out = new FastXmlSerializer();
6957                out.setOutput(memStream, StandardCharsets.UTF_8.name());
6958                writeDailyItemsLocked(out);
6959                BackgroundThread.getHandler().post(new Runnable() {
6960                    @Override
6961                    public void run() {
6962                        synchronized (mCheckinFile) {
6963                            FileOutputStream stream = null;
6964                            try {
6965                                stream = mDailyFile.startWrite();
6966                                memStream.writeTo(stream);
6967                                stream.flush();
6968                                FileUtils.sync(stream);
6969                                stream.close();
6970                                mDailyFile.finishWrite(stream);
6971                            } catch (IOException e) {
6972                                Slog.w("BatteryStats",
6973                                        "Error writing battery daily items", e);
6974                                mDailyFile.failWrite(stream);
6975                            }
6976                        }
6977                    }
6978                });
6979            } catch (IOException e) {
6980            }
6981        }
6982    }
6983
6984    private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
6985        StringBuilder sb = new StringBuilder(64);
6986        out.startDocument(null, true);
6987        out.startTag(null, "daily-items");
6988        for (int i=0; i<mDailyItems.size(); i++) {
6989            final DailyItem dit = mDailyItems.get(i);
6990            out.startTag(null, "item");
6991            out.attribute(null, "start", Long.toString(dit.mStartTime));
6992            out.attribute(null, "end", Long.toString(dit.mEndTime));
6993            writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
6994            writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
6995            if (dit.mPackageChanges != null) {
6996                for (int j=0; j<dit.mPackageChanges.size(); j++) {
6997                    PackageChange pc = dit.mPackageChanges.get(j);
6998                    if (pc.mUpdate) {
6999                        out.startTag(null, "upd");
7000                        out.attribute(null, "pkg", pc.mPackageName);
7001                        out.attribute(null, "ver", Integer.toString(pc.mVersionCode));
7002                        out.endTag(null, "upd");
7003                    } else {
7004                        out.startTag(null, "rem");
7005                        out.attribute(null, "pkg", pc.mPackageName);
7006                        out.endTag(null, "rem");
7007                    }
7008                }
7009            }
7010            out.endTag(null, "item");
7011        }
7012        out.endTag(null, "daily-items");
7013        out.endDocument();
7014    }
7015
7016    private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
7017            StringBuilder tmpBuilder) throws IOException {
7018        if (steps != null) {
7019            out.startTag(null, tag);
7020            out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
7021            for (int i=0; i<steps.mNumStepDurations; i++) {
7022                out.startTag(null, "s");
7023                tmpBuilder.setLength(0);
7024                steps.encodeEntryAt(i, tmpBuilder);
7025                out.attribute(null, "v", tmpBuilder.toString());
7026                out.endTag(null, "s");
7027            }
7028            out.endTag(null, tag);
7029        }
7030    }
7031
7032    public void readDailyStatsLocked() {
7033        Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
7034        mDailyItems.clear();
7035        FileInputStream stream;
7036        try {
7037            stream = mDailyFile.openRead();
7038        } catch (FileNotFoundException e) {
7039            return;
7040        }
7041        try {
7042            XmlPullParser parser = Xml.newPullParser();
7043            parser.setInput(stream, StandardCharsets.UTF_8.name());
7044            readDailyItemsLocked(parser);
7045        } catch (XmlPullParserException e) {
7046        } finally {
7047            try {
7048                stream.close();
7049            } catch (IOException e) {
7050            }
7051        }
7052    }
7053
7054    private void readDailyItemsLocked(XmlPullParser parser) {
7055        try {
7056            int type;
7057            while ((type = parser.next()) != XmlPullParser.START_TAG
7058                    && type != XmlPullParser.END_DOCUMENT) {
7059                ;
7060            }
7061
7062            if (type != XmlPullParser.START_TAG) {
7063                throw new IllegalStateException("no start tag found");
7064            }
7065
7066            int outerDepth = parser.getDepth();
7067            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7068                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7069                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7070                    continue;
7071                }
7072
7073                String tagName = parser.getName();
7074                if (tagName.equals("item")) {
7075                    readDailyItemTagLocked(parser);
7076                } else {
7077                    Slog.w(TAG, "Unknown element under <daily-items>: "
7078                            + parser.getName());
7079                    XmlUtils.skipCurrentTag(parser);
7080                }
7081            }
7082
7083        } catch (IllegalStateException e) {
7084            Slog.w(TAG, "Failed parsing daily " + e);
7085        } catch (NullPointerException e) {
7086            Slog.w(TAG, "Failed parsing daily " + e);
7087        } catch (NumberFormatException e) {
7088            Slog.w(TAG, "Failed parsing daily " + e);
7089        } catch (XmlPullParserException e) {
7090            Slog.w(TAG, "Failed parsing daily " + e);
7091        } catch (IOException e) {
7092            Slog.w(TAG, "Failed parsing daily " + e);
7093        } catch (IndexOutOfBoundsException e) {
7094            Slog.w(TAG, "Failed parsing daily " + e);
7095        }
7096    }
7097
7098    void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
7099            XmlPullParserException, IOException {
7100        DailyItem dit = new DailyItem();
7101        String attr = parser.getAttributeValue(null, "start");
7102        if (attr != null) {
7103            dit.mStartTime = Long.parseLong(attr);
7104        }
7105        attr = parser.getAttributeValue(null, "end");
7106        if (attr != null) {
7107            dit.mEndTime = Long.parseLong(attr);
7108        }
7109        int outerDepth = parser.getDepth();
7110        int type;
7111        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7112                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7113            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7114                continue;
7115            }
7116
7117            String tagName = parser.getName();
7118            if (tagName.equals("dis")) {
7119                readDailyItemTagDetailsLocked(parser, dit, false, "dis");
7120            } else if (tagName.equals("chg")) {
7121                readDailyItemTagDetailsLocked(parser, dit, true, "chg");
7122            } else if (tagName.equals("upd")) {
7123                if (dit.mPackageChanges == null) {
7124                    dit.mPackageChanges = new ArrayList<>();
7125                }
7126                PackageChange pc = new PackageChange();
7127                pc.mUpdate = true;
7128                pc.mPackageName = parser.getAttributeValue(null, "pkg");
7129                String verStr = parser.getAttributeValue(null, "ver");
7130                pc.mVersionCode = verStr != null ? Integer.parseInt(verStr) : 0;
7131                dit.mPackageChanges.add(pc);
7132                XmlUtils.skipCurrentTag(parser);
7133            } else if (tagName.equals("rem")) {
7134                if (dit.mPackageChanges == null) {
7135                    dit.mPackageChanges = new ArrayList<>();
7136                }
7137                PackageChange pc = new PackageChange();
7138                pc.mUpdate = false;
7139                pc.mPackageName = parser.getAttributeValue(null, "pkg");
7140                dit.mPackageChanges.add(pc);
7141                XmlUtils.skipCurrentTag(parser);
7142            } else {
7143                Slog.w(TAG, "Unknown element under <item>: "
7144                        + parser.getName());
7145                XmlUtils.skipCurrentTag(parser);
7146            }
7147        }
7148        mDailyItems.add(dit);
7149    }
7150
7151    void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
7152            String tag)
7153            throws NumberFormatException, XmlPullParserException, IOException {
7154        final String numAttr = parser.getAttributeValue(null, "n");
7155        if (numAttr == null) {
7156            Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
7157            XmlUtils.skipCurrentTag(parser);
7158            return;
7159        }
7160        final int num = Integer.parseInt(numAttr);
7161        LevelStepTracker steps = new LevelStepTracker(num);
7162        if (isCharge) {
7163            dit.mChargeSteps = steps;
7164        } else {
7165            dit.mDischargeSteps = steps;
7166        }
7167        int i = 0;
7168        int outerDepth = parser.getDepth();
7169        int type;
7170        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7171                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7172            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7173                continue;
7174            }
7175
7176            String tagName = parser.getName();
7177            if ("s".equals(tagName)) {
7178                if (i < num) {
7179                    String valueAttr = parser.getAttributeValue(null, "v");
7180                    if (valueAttr != null) {
7181                        steps.decodeEntryAt(i, valueAttr);
7182                        i++;
7183                    }
7184                }
7185            } else {
7186                Slog.w(TAG, "Unknown element under <" + tag + ">: "
7187                        + parser.getName());
7188                XmlUtils.skipCurrentTag(parser);
7189            }
7190        }
7191        steps.mNumStepDurations = i;
7192    }
7193
7194    @Override
7195    public DailyItem getDailyItemLocked(int daysAgo) {
7196        int index = mDailyItems.size()-1-daysAgo;
7197        return index >= 0 ? mDailyItems.get(index) : null;
7198    }
7199
7200    @Override
7201    public long getCurrentDailyStartTime() {
7202        return mDailyStartTime;
7203    }
7204
7205    @Override
7206    public long getNextMinDailyDeadline() {
7207        return mNextMinDailyDeadline;
7208    }
7209
7210    @Override
7211    public long getNextMaxDailyDeadline() {
7212        return mNextMaxDailyDeadline;
7213    }
7214
7215    @Override
7216    public boolean startIteratingOldHistoryLocked() {
7217        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
7218                + " pos=" + mHistoryBuffer.dataPosition());
7219        if ((mHistoryIterator = mHistory) == null) {
7220            return false;
7221        }
7222        mHistoryBuffer.setDataPosition(0);
7223        mHistoryReadTmp.clear();
7224        mReadOverflow = false;
7225        mIteratingHistory = true;
7226        return true;
7227    }
7228
7229    @Override
7230    public boolean getNextOldHistoryLocked(HistoryItem out) {
7231        boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
7232        if (!end) {
7233            readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
7234            mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
7235        }
7236        HistoryItem cur = mHistoryIterator;
7237        if (cur == null) {
7238            if (!mReadOverflow && !end) {
7239                Slog.w(TAG, "Old history ends before new history!");
7240            }
7241            return false;
7242        }
7243        out.setTo(cur);
7244        mHistoryIterator = cur.next;
7245        if (!mReadOverflow) {
7246            if (end) {
7247                Slog.w(TAG, "New history ends before old history!");
7248            } else if (!out.same(mHistoryReadTmp)) {
7249                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
7250                pw.println("Histories differ!");
7251                pw.println("Old history:");
7252                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
7253                pw.println("New history:");
7254                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
7255                        true);
7256                pw.flush();
7257            }
7258        }
7259        return true;
7260    }
7261
7262    @Override
7263    public void finishIteratingOldHistoryLocked() {
7264        mIteratingHistory = false;
7265        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
7266        mHistoryIterator = null;
7267    }
7268
7269    public int getHistoryTotalSize() {
7270        return MAX_HISTORY_BUFFER;
7271    }
7272
7273    public int getHistoryUsedSize() {
7274        return mHistoryBuffer.dataSize();
7275    }
7276
7277    @Override
7278    public boolean startIteratingHistoryLocked() {
7279        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
7280                + " pos=" + mHistoryBuffer.dataPosition());
7281        if (mHistoryBuffer.dataSize() <= 0) {
7282            return false;
7283        }
7284        mHistoryBuffer.setDataPosition(0);
7285        mReadOverflow = false;
7286        mIteratingHistory = true;
7287        mReadHistoryStrings = new String[mHistoryTagPool.size()];
7288        mReadHistoryUids = new int[mHistoryTagPool.size()];
7289        mReadHistoryChars = 0;
7290        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
7291            final HistoryTag tag = ent.getKey();
7292            final int idx = ent.getValue();
7293            mReadHistoryStrings[idx] = tag.string;
7294            mReadHistoryUids[idx] = tag.uid;
7295            mReadHistoryChars += tag.string.length() + 1;
7296        }
7297        return true;
7298    }
7299
7300    @Override
7301    public int getHistoryStringPoolSize() {
7302        return mReadHistoryStrings.length;
7303    }
7304
7305    @Override
7306    public int getHistoryStringPoolBytes() {
7307        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
7308        // Each string character is 2 bytes.
7309        return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
7310    }
7311
7312    @Override
7313    public String getHistoryTagPoolString(int index) {
7314        return mReadHistoryStrings[index];
7315    }
7316
7317    @Override
7318    public int getHistoryTagPoolUid(int index) {
7319        return mReadHistoryUids[index];
7320    }
7321
7322    @Override
7323    public boolean getNextHistoryLocked(HistoryItem out) {
7324        final int pos = mHistoryBuffer.dataPosition();
7325        if (pos == 0) {
7326            out.clear();
7327        }
7328        boolean end = pos >= mHistoryBuffer.dataSize();
7329        if (end) {
7330            return false;
7331        }
7332
7333        final long lastRealtime = out.time;
7334        final long lastWalltime = out.currentTime;
7335        readHistoryDelta(mHistoryBuffer, out);
7336        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
7337                && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
7338            out.currentTime = lastWalltime + (out.time - lastRealtime);
7339        }
7340        return true;
7341    }
7342
7343    @Override
7344    public void finishIteratingHistoryLocked() {
7345        mIteratingHistory = false;
7346        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
7347        mReadHistoryStrings = null;
7348    }
7349
7350    @Override
7351    public long getHistoryBaseTime() {
7352        return mHistoryBaseTime;
7353    }
7354
7355    @Override
7356    public int getStartCount() {
7357        return mStartCount;
7358    }
7359
7360    public boolean isOnBattery() {
7361        return mOnBattery;
7362    }
7363
7364    public boolean isCharging() {
7365        return mCharging;
7366    }
7367
7368    public boolean isScreenOn() {
7369        return mScreenState == Display.STATE_ON;
7370    }
7371
7372    void initTimes(long uptime, long realtime) {
7373        mStartClockTime = System.currentTimeMillis();
7374        mOnBatteryTimeBase.init(uptime, realtime);
7375        mOnBatteryScreenOffTimeBase.init(uptime, realtime);
7376        mRealtime = 0;
7377        mUptime = 0;
7378        mRealtimeStart = realtime;
7379        mUptimeStart = uptime;
7380    }
7381
7382    void initDischarge() {
7383        mLowDischargeAmountSinceCharge = 0;
7384        mHighDischargeAmountSinceCharge = 0;
7385        mDischargeAmountScreenOn = 0;
7386        mDischargeAmountScreenOnSinceCharge = 0;
7387        mDischargeAmountScreenOff = 0;
7388        mDischargeAmountScreenOffSinceCharge = 0;
7389        mDischargeStepTracker.init();
7390        mChargeStepTracker.init();
7391    }
7392
7393    public void resetAllStatsCmdLocked() {
7394        resetAllStatsLocked();
7395        final long mSecUptime = SystemClock.uptimeMillis();
7396        long uptime = mSecUptime * 1000;
7397        long mSecRealtime = SystemClock.elapsedRealtime();
7398        long realtime = mSecRealtime * 1000;
7399        mDischargeStartLevel = mHistoryCur.batteryLevel;
7400        pullPendingStateUpdatesLocked();
7401        addHistoryRecordLocked(mSecRealtime, mSecUptime);
7402        mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
7403                = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
7404        mOnBatteryTimeBase.reset(uptime, realtime);
7405        mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
7406        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
7407            if (mScreenState == Display.STATE_ON) {
7408                mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
7409                mDischargeScreenOffUnplugLevel = 0;
7410            } else {
7411                mDischargeScreenOnUnplugLevel = 0;
7412                mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
7413            }
7414            mDischargeAmountScreenOn = 0;
7415            mDischargeAmountScreenOff = 0;
7416        }
7417        initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
7418    }
7419
7420    private void resetAllStatsLocked() {
7421        mStartCount = 0;
7422        initTimes(SystemClock.uptimeMillis() * 1000, SystemClock.elapsedRealtime() * 1000);
7423        mScreenOnTimer.reset(false);
7424        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
7425            mScreenBrightnessTimer[i].reset(false);
7426        }
7427        mInteractiveTimer.reset(false);
7428        mPowerSaveModeEnabledTimer.reset(false);
7429        mDeviceIdleModeEnabledTimer.reset(false);
7430        mDeviceIdlingTimer.reset(false);
7431        mPhoneOnTimer.reset(false);
7432        mAudioOnTimer.reset(false);
7433        mVideoOnTimer.reset(false);
7434        mFlashlightOnTimer.reset(false);
7435        mCameraOnTimer.reset(false);
7436        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
7437            mPhoneSignalStrengthsTimer[i].reset(false);
7438        }
7439        mPhoneSignalScanningTimer.reset(false);
7440        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
7441            mPhoneDataConnectionsTimer[i].reset(false);
7442        }
7443        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7444            mNetworkByteActivityCounters[i].reset(false);
7445            mNetworkPacketActivityCounters[i].reset(false);
7446        }
7447        mMobileRadioActiveTimer.reset(false);
7448        mMobileRadioActivePerAppTimer.reset(false);
7449        mMobileRadioActiveAdjustedTime.reset(false);
7450        mMobileRadioActiveUnknownTime.reset(false);
7451        mMobileRadioActiveUnknownCount.reset(false);
7452        mWifiOnTimer.reset(false);
7453        mGlobalWifiRunningTimer.reset(false);
7454        for (int i=0; i<NUM_WIFI_STATES; i++) {
7455            mWifiStateTimer[i].reset(false);
7456        }
7457        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
7458            mWifiSupplStateTimer[i].reset(false);
7459        }
7460        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7461            mWifiSignalStrengthsTimer[i].reset(false);
7462        }
7463        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
7464            mBluetoothActivityCounters[i].reset(false);
7465            mWifiActivityCounters[i].reset(false);
7466        }
7467        mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
7468
7469        for (int i=0; i<mUidStats.size(); i++) {
7470            if (mUidStats.valueAt(i).reset()) {
7471                mUidStats.remove(mUidStats.keyAt(i));
7472                i--;
7473            }
7474        }
7475
7476        if (mKernelWakelockStats.size() > 0) {
7477            for (SamplingTimer timer : mKernelWakelockStats.values()) {
7478                mOnBatteryScreenOffTimeBase.remove(timer);
7479            }
7480            mKernelWakelockStats.clear();
7481        }
7482
7483        if (mWakeupReasonStats.size() > 0) {
7484            for (SamplingTimer timer : mWakeupReasonStats.values()) {
7485                mOnBatteryTimeBase.remove(timer);
7486            }
7487            mWakeupReasonStats.clear();
7488        }
7489
7490        mLastHistoryStepDetails = null;
7491        mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
7492        mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
7493        mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
7494        mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
7495        mLastStepStatUserTime = mCurStepStatUserTime = 0;
7496        mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
7497        mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
7498        mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
7499        mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
7500        mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
7501
7502        initDischarge();
7503
7504        clearHistoryLocked();
7505    }
7506
7507    private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
7508        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
7509            if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
7510                // Not recording process starts/stops.
7511                continue;
7512            }
7513            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
7514            if (active == null) {
7515                continue;
7516            }
7517            for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
7518                SparseIntArray uids = ent.getValue();
7519                for (int j=0; j<uids.size(); j++) {
7520                    addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
7521                            uids.keyAt(j));
7522                }
7523            }
7524        }
7525    }
7526
7527    void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
7528        if (oldScreenOn) {
7529            int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
7530            if (diff > 0) {
7531                mDischargeAmountScreenOn += diff;
7532                mDischargeAmountScreenOnSinceCharge += diff;
7533            }
7534        } else {
7535            int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
7536            if (diff > 0) {
7537                mDischargeAmountScreenOff += diff;
7538                mDischargeAmountScreenOffSinceCharge += diff;
7539            }
7540        }
7541        if (newScreenOn) {
7542            mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
7543            mDischargeScreenOffUnplugLevel = 0;
7544        } else {
7545            mDischargeScreenOnUnplugLevel = 0;
7546            mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
7547        }
7548    }
7549
7550    public void pullPendingStateUpdatesLocked() {
7551        if (mOnBatteryInternal) {
7552            final boolean screenOn = mScreenState == Display.STATE_ON;
7553            updateDischargeScreenLevelsLocked(screenOn, screenOn);
7554        }
7555    }
7556
7557    private String[] mMobileIfaces = EmptyArray.STRING;
7558    private String[] mWifiIfaces = EmptyArray.STRING;
7559
7560    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
7561
7562    private static final int NETWORK_STATS_LAST = 0;
7563    private static final int NETWORK_STATS_NEXT = 1;
7564    private static final int NETWORK_STATS_DELTA = 2;
7565
7566    private final NetworkStats[] mMobileNetworkStats = new NetworkStats[] {
7567            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7568            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7569            new NetworkStats(SystemClock.elapsedRealtime(), 50)
7570    };
7571
7572    private final NetworkStats[] mWifiNetworkStats = new NetworkStats[] {
7573            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7574            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7575            new NetworkStats(SystemClock.elapsedRealtime(), 50)
7576    };
7577
7578    /**
7579     * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
7580     * as a buffer of NetworkStats objects to cycle through when computing deltas.
7581     */
7582    private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
7583                                                    NetworkStats[] networkStatsBuffer)
7584            throws IOException {
7585        if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
7586                false)) {
7587            return null;
7588        }
7589
7590        final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
7591                ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
7592        networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
7593                networkStatsBuffer[NETWORK_STATS_LAST], null, null,
7594                networkStatsBuffer[NETWORK_STATS_DELTA]);
7595        networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
7596        networkStatsBuffer[NETWORK_STATS_LAST] = stats;
7597        return networkStatsBuffer[NETWORK_STATS_DELTA];
7598    }
7599
7600    /**
7601     * Distribute WiFi energy info and network traffic to apps.
7602     * @param info The energy information from the WiFi controller.
7603     */
7604    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
7605        if (DEBUG_ENERGY) {
7606            Slog.d(TAG, "Updating wifi stats");
7607        }
7608
7609        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
7610        NetworkStats delta = null;
7611        try {
7612            if (!ArrayUtils.isEmpty(mWifiIfaces)) {
7613                delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
7614            }
7615        } catch (IOException e) {
7616            Slog.wtf(TAG, "Failed to get wifi network stats", e);
7617            return;
7618        }
7619
7620        if (!mOnBatteryInternal) {
7621            return;
7622        }
7623
7624        SparseLongArray rxPackets = new SparseLongArray();
7625        SparseLongArray txPackets = new SparseLongArray();
7626        long totalTxPackets = 0;
7627        long totalRxPackets = 0;
7628        if (delta != null) {
7629            final int size = delta.size();
7630            for (int i = 0; i < size; i++) {
7631                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
7632
7633                if (DEBUG_ENERGY) {
7634                    Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
7635                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
7636                            + " txPackets=" + entry.txPackets);
7637                }
7638
7639                if (entry.rxBytes == 0 || entry.txBytes == 0) {
7640                    continue;
7641                }
7642
7643                final Uid u = getUidStatsLocked(mapUid(entry.uid));
7644                u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
7645                        entry.rxPackets);
7646                u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
7647                        entry.txPackets);
7648                rxPackets.put(u.getUid(), entry.rxPackets);
7649                txPackets.put(u.getUid(), entry.txPackets);
7650
7651                // Sum the total number of packets so that the Rx Power and Tx Power can
7652                // be evenly distributed amongst the apps.
7653                totalRxPackets += entry.rxPackets;
7654                totalTxPackets += entry.txPackets;
7655
7656                mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
7657                        entry.rxBytes);
7658                mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
7659                        entry.txBytes);
7660                mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
7661                        entry.rxPackets);
7662                mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
7663                        entry.txPackets);
7664            }
7665        }
7666
7667        if (info != null) {
7668            mHasWifiEnergyReporting = true;
7669
7670            // Measured in mAms
7671            final long txTimeMs = info.getControllerTxTimeMillis();
7672            final long rxTimeMs = info.getControllerRxTimeMillis();
7673            final long idleTimeMs = info.getControllerIdleTimeMillis();
7674            final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
7675
7676            long leftOverRxTimeMs = rxTimeMs;
7677
7678            if (DEBUG_ENERGY) {
7679                Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
7680                Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
7681                Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
7682                Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
7683                Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
7684            }
7685
7686            long totalWifiLockTimeMs = 0;
7687            long totalScanTimeMs = 0;
7688
7689            // On the first pass, collect some totals so that we can normalize power
7690            // calculations if we need to.
7691            final int uidStatsSize = mUidStats.size();
7692            for (int i = 0; i < uidStatsSize; i++) {
7693                final Uid uid = mUidStats.valueAt(i);
7694
7695                // Sum the total scan power for all apps.
7696                totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
7697                        elapsedRealtimeMs * 1000) / 1000;
7698
7699                // Sum the total time holding wifi lock for all apps.
7700                totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
7701                        elapsedRealtimeMs * 1000) / 1000;
7702            }
7703
7704            if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
7705                Slog.d(TAG, "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
7706                        + rxTimeMs + " ms). Normalizing scan time.");
7707            }
7708
7709            // Actually assign and distribute power usage to apps.
7710            for (int i = 0; i < uidStatsSize; i++) {
7711                final Uid uid = mUidStats.valueAt(i);
7712
7713                long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
7714                        elapsedRealtimeMs * 1000) / 1000;
7715                if (scanTimeSinceMarkMs > 0) {
7716                    // Set the new mark so that next time we get new data since this point.
7717                    uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
7718
7719                    if (totalScanTimeMs > rxTimeMs) {
7720                        // Our total scan time is more than the reported Rx time.
7721                        // This is possible because the cost of a scan is approximate.
7722                        // Let's normalize the result so that we evenly blame each app
7723                        // scanning.
7724                        //
7725                        // This means that we may have apps that received packets not be blamed
7726                        // for this, but this is fine as scans are relatively more expensive.
7727                        scanTimeSinceMarkMs = (rxTimeMs * scanTimeSinceMarkMs) / totalScanTimeMs;
7728                    }
7729
7730                    if (DEBUG_ENERGY) {
7731                        Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": "
7732                                + scanTimeSinceMarkMs + " ms)");
7733                    }
7734                    uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, scanTimeSinceMarkMs);
7735                    leftOverRxTimeMs -= scanTimeSinceMarkMs;
7736                }
7737
7738                // Distribute evenly the power consumed while Idle to each app holding a WiFi
7739                // lock.
7740                final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
7741                        elapsedRealtimeMs * 1000) / 1000;
7742                if (wifiLockTimeSinceMarkMs > 0) {
7743                    // Set the new mark so that next time we get new data since this point.
7744                    uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
7745
7746                    final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
7747                            / totalWifiLockTimeMs;
7748                    if (DEBUG_ENERGY) {
7749                        Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
7750                                + myIdleTimeMs + " ms");
7751                    }
7752                    uid.noteWifiControllerActivityLocked(CONTROLLER_IDLE_TIME, myIdleTimeMs);
7753                }
7754            }
7755
7756            if (DEBUG_ENERGY) {
7757                Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
7758            }
7759
7760            // Distribute the Tx power appropriately between all apps that transmitted packets.
7761            for (int i = 0; i < txPackets.size(); i++) {
7762                final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
7763                final long myTxTimeMs = (txPackets.valueAt(i) * txTimeMs) / totalTxPackets;
7764                if (DEBUG_ENERGY) {
7765                    Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
7766                }
7767                uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, myTxTimeMs);
7768            }
7769
7770            // Distribute the remaining Rx power appropriately between all apps that received
7771            // packets.
7772            for (int i = 0; i < rxPackets.size(); i++) {
7773                final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
7774                final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
7775                if (DEBUG_ENERGY) {
7776                    Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
7777                }
7778                uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, myRxTimeMs);
7779            }
7780
7781            // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
7782
7783            // Update WiFi controller stats.
7784            mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
7785                    info.getControllerRxTimeMillis());
7786            mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
7787                    info.getControllerTxTimeMillis());
7788            mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
7789                    info.getControllerIdleTimeMillis());
7790
7791            // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
7792            final double opVolt = mPowerProfile.getAveragePower(
7793                    PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
7794            if (opVolt != 0) {
7795                // We store the power drain as mAms.
7796                mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
7797                        (long)(info.getControllerEnergyUsed() / opVolt));
7798            }
7799        }
7800    }
7801
7802    /**
7803     * Distribute Cell radio energy info and network traffic to apps.
7804     */
7805    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
7806        if (DEBUG_ENERGY) {
7807            Slog.d(TAG, "Updating mobile radio stats");
7808        }
7809
7810        NetworkStats delta = null;
7811        try {
7812            if (!ArrayUtils.isEmpty(mMobileIfaces)) {
7813                delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
7814            }
7815        } catch (IOException e) {
7816            Slog.wtf(TAG, "Failed to get mobile network stats", e);
7817            return;
7818        }
7819
7820        if (delta == null || !mOnBatteryInternal) {
7821            return;
7822        }
7823
7824        long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
7825                elapsedRealtimeMs * 1000);
7826        mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
7827        long totalPackets = delta.getTotalPackets();
7828
7829        final int size = delta.size();
7830        for (int i = 0; i < size; i++) {
7831            final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
7832
7833            if (entry.rxBytes == 0 || entry.txBytes == 0) {
7834                continue;
7835            }
7836
7837            if (DEBUG_ENERGY) {
7838                Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
7839                        + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
7840                        + " txPackets=" + entry.txPackets);
7841            }
7842
7843            final Uid u = getUidStatsLocked(mapUid(entry.uid));
7844            u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
7845                    entry.rxPackets);
7846            u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
7847                    entry.txPackets);
7848
7849            if (radioTime > 0) {
7850                // Distribute total radio active time in to this app.
7851                long appPackets = entry.rxPackets + entry.txPackets;
7852                long appRadioTime = (radioTime*appPackets)/totalPackets;
7853                u.noteMobileRadioActiveTimeLocked(appRadioTime);
7854                // Remove this app from the totals, so that we don't lose any time
7855                // due to rounding.
7856                radioTime -= appRadioTime;
7857                totalPackets -= appPackets;
7858            }
7859
7860            mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
7861                    entry.rxBytes);
7862            mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
7863                    entry.txBytes);
7864            mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
7865                    entry.rxPackets);
7866            mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
7867                    entry.txPackets);
7868        }
7869
7870        if (radioTime > 0) {
7871            // Whoops, there is some radio time we can't blame on an app!
7872            mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
7873            mMobileRadioActiveUnknownCount.addCountLocked(1);
7874        }
7875    }
7876
7877    /**
7878     * Distribute Bluetooth energy info and network traffic to apps.
7879     * @param info The energy information from the bluetooth controller.
7880     */
7881    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
7882        if (DEBUG_ENERGY) {
7883            Slog.d(TAG, "Updating bluetooth stats");
7884        }
7885
7886        if (info != null && mOnBatteryInternal) {
7887            mHasBluetoothEnergyReporting = true;
7888            mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
7889                    info.getControllerRxTimeMillis());
7890            mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
7891                    info.getControllerTxTimeMillis());
7892            mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
7893                    info.getControllerIdleTimeMillis());
7894
7895            // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
7896            final double opVolt = mPowerProfile.getAveragePower(
7897                    PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
7898            if (opVolt != 0) {
7899                // We store the power drain as mAms.
7900                mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
7901                        (long) (info.getControllerEnergyUsed() / opVolt));
7902            }
7903        }
7904    }
7905
7906    /**
7907     * Read and distribute kernel wake lock use across apps.
7908     */
7909    public void updateKernelWakelocksLocked() {
7910        final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
7911                mTmpWakelockStats);
7912        if (wakelockStats == null) {
7913            // Not crashing might make board bringup easier.
7914            Slog.w(TAG, "Couldn't get kernel wake lock stats");
7915            return;
7916        }
7917
7918        // Record whether we've seen a non-zero time (for debugging b/22716723).
7919        boolean seenNonZeroTime = false;
7920        for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
7921            String name = ent.getKey();
7922            KernelWakelockStats.Entry kws = ent.getValue();
7923
7924            SamplingTimer kwlt = mKernelWakelockStats.get(name);
7925            if (kwlt == null) {
7926                kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
7927                        true /* track reported val */);
7928                mKernelWakelockStats.put(name, kwlt);
7929            }
7930            kwlt.updateCurrentReportedCount(kws.mCount);
7931            kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
7932            kwlt.setUpdateVersion(kws.mVersion);
7933
7934            if (kws.mVersion != wakelockStats.kernelWakelockVersion)
7935            seenNonZeroTime |= kws.mTotalTime > 0;
7936        }
7937
7938        int numWakelocksSetStale = 0;
7939        if (wakelockStats.size() != mKernelWakelockStats.size()) {
7940            // Set timers to stale if they didn't appear in /proc/wakelocks this time.
7941            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
7942                SamplingTimer st = ent.getValue();
7943                if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
7944                    st.setStale();
7945                    numWakelocksSetStale++;
7946                }
7947            }
7948        }
7949
7950        if (!seenNonZeroTime) {
7951            Slog.wtf(TAG, "All kernel wakelocks had time of zero");
7952        }
7953
7954        if (numWakelocksSetStale == mKernelWakelockStats.size()) {
7955            Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
7956                    wakelockStats.kernelWakelockVersion);
7957        }
7958    }
7959
7960    // We use an anonymous class to access these variables,
7961    // so they can't live on the stack or they'd have to be
7962    // final MutableLong objects (more allocations).
7963    // Used in updateCpuTimeLocked().
7964    long mTempTotalCpuUserTimeUs;
7965    long mTempTotalCpuSystemTimeUs;
7966
7967    /**
7968     * Read and distribute CPU usage across apps. If their are partial wakelocks being held
7969     * and we are on battery with screen off, we give more of the cpu time to those apps holding
7970     * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
7971     */
7972    public void updateCpuTimeLocked() {
7973        if (DEBUG_ENERGY_CPU) {
7974            Slog.d(TAG, "!Cpu updating!");
7975        }
7976
7977        // Holding a wakelock costs more than just using the cpu.
7978        // Currently, we assign only half the cpu time to an app that is running but
7979        // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
7980        // If no app is holding a wakelock, then the distribution is normal.
7981        final int wakelockWeight = 50;
7982
7983        // Read the time spent at various cpu frequencies.
7984        final int cpuSpeedSteps = getCpuSpeedSteps();
7985        final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta();
7986
7987        int numWakelocks = 0;
7988
7989        // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
7990        // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
7991        final int numPartialTimers = mPartialTimers.size();
7992        if (mOnBatteryScreenOffTimeBase.isRunning()) {
7993            for (int i = 0; i < numPartialTimers; i++) {
7994                final StopwatchTimer timer = mPartialTimers.get(i);
7995                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
7996                    // Since the collection and blaming of wakelocks can be scheduled to run after
7997                    // some delay, the mPartialTimers list may have new entries. We can't blame
7998                    // the newly added timer for past cpu time, so we only consider timers that
7999                    // were present for one round of collection. Once a timer has gone through
8000                    // a round of collection, its mInList field is set to true.
8001                    numWakelocks++;
8002                }
8003            }
8004        }
8005
8006        final int numWakelocksF = numWakelocks;
8007        mTempTotalCpuUserTimeUs = 0;
8008        mTempTotalCpuSystemTimeUs = 0;
8009
8010        // Read the CPU data for each UID. This will internally generate a snapshot so next time
8011        // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
8012        // we just ignore the data.
8013        final long startTimeMs = SystemClock.elapsedRealtime();
8014        mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
8015                new KernelUidCpuTimeReader.Callback() {
8016                    @Override
8017                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
8018                                             long powerMaUs) {
8019                        final Uid u = getUidStatsLocked(mapUid(uid));
8020
8021                        // Accumulate the total system and user time.
8022                        mTempTotalCpuUserTimeUs += userTimeUs;
8023                        mTempTotalCpuSystemTimeUs += systemTimeUs;
8024
8025                        StringBuilder sb = null;
8026                        if (DEBUG_ENERGY_CPU) {
8027                            sb = new StringBuilder();
8028                            sb.append("  got time for uid=").append(u.mUid).append(": u=");
8029                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
8030                            sb.append(" s=");
8031                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
8032                            sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
8033                        }
8034
8035                        if (numWakelocksF > 0) {
8036                            // We have wakelocks being held, so only give a portion of the
8037                            // time to the process. The rest will be distributed among wakelock
8038                            // holders.
8039                            userTimeUs = (userTimeUs * wakelockWeight) / 100;
8040                            systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
8041                        }
8042
8043                        if (sb != null) {
8044                            sb.append("  adding to uid=").append(u.mUid).append(": u=");
8045                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
8046                            sb.append(" s=");
8047                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
8048                            sb.append(" p=").append(powerMaUs / 1000).append("mAms");
8049                            Slog.d(TAG, sb.toString());
8050                        }
8051
8052                        u.mUserCpuTime.addCountLocked(userTimeUs);
8053                        u.mSystemCpuTime.addCountLocked(systemTimeUs);
8054                        u.mCpuPower.addCountLocked(powerMaUs);
8055
8056                        // Add the cpu speeds to this UID. These are used as a ratio
8057                        // for computing the power this UID used.
8058                        for (int i = 0; i < cpuSpeedSteps; i++) {
8059                            if (u.mSpeedBins[i] == null) {
8060                                u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
8061                            }
8062                            u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
8063                        }
8064                    }
8065                });
8066
8067        if (DEBUG_ENERGY_CPU) {
8068            Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) +
8069                    " ms");
8070        }
8071
8072        if (mOnBatteryInternal && numWakelocks > 0) {
8073            // Distribute a portion of the total cpu time to wakelock holders.
8074            mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
8075            mTempTotalCpuSystemTimeUs =
8076                    (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
8077
8078            for (int i = 0; i < numPartialTimers; i++) {
8079                final StopwatchTimer timer = mPartialTimers.get(i);
8080
8081                // The system does not share any blame, as it is usually holding the wakelock
8082                // on behalf of an app.
8083                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
8084                    int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
8085                    int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
8086
8087                    if (DEBUG_ENERGY_CPU) {
8088                        StringBuilder sb = new StringBuilder();
8089                        sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
8090                                .append(": u=");
8091                        TimeUtils.formatDuration(userTimeUs / 1000, sb);
8092                        sb.append(" s=");
8093                        TimeUtils.formatDuration(systemTimeUs / 1000, sb);
8094                        Slog.d(TAG, sb.toString());
8095                    }
8096
8097                    timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
8098                    timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
8099
8100                    final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
8101                    proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
8102
8103                    mTempTotalCpuUserTimeUs -= userTimeUs;
8104                    mTempTotalCpuSystemTimeUs -= systemTimeUs;
8105                    numWakelocks--;
8106                }
8107            }
8108
8109            if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
8110                // Anything left over is given to the system.
8111                if (DEBUG_ENERGY_CPU) {
8112                    StringBuilder sb = new StringBuilder();
8113                    sb.append("  Distributing lost time to system: u=");
8114                    TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
8115                    sb.append(" s=");
8116                    TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
8117                    Slog.d(TAG, sb.toString());
8118                }
8119
8120                final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
8121                u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
8122                u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
8123
8124                final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
8125                proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000,
8126                        (int) mTempTotalCpuSystemTimeUs / 1000);
8127            }
8128        }
8129
8130        // See if there is a difference in wakelocks between this collection and the last
8131        // collection.
8132        if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
8133            // No difference, so each timer is now considered for the next collection.
8134            for (int i = 0; i < numPartialTimers; i++) {
8135                mPartialTimers.get(i).mInList = true;
8136            }
8137        } else {
8138            // The lists are different, meaning we added (or removed a timer) since the last
8139            // collection.
8140            final int numLastPartialTimers = mLastPartialTimers.size();
8141            for (int i = 0; i < numLastPartialTimers; i++) {
8142                mLastPartialTimers.get(i).mInList = false;
8143            }
8144            mLastPartialTimers.clear();
8145
8146            // Mark the current timers as gone through a collection.
8147            for (int i = 0; i < numPartialTimers; i++) {
8148                final StopwatchTimer timer = mPartialTimers.get(i);
8149                timer.mInList = true;
8150                mLastPartialTimers.add(timer);
8151            }
8152        }
8153    }
8154
8155    boolean setChargingLocked(boolean charging) {
8156        if (mCharging != charging) {
8157            mCharging = charging;
8158            if (charging) {
8159                mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
8160            } else {
8161                mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
8162            }
8163            mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
8164            return true;
8165        }
8166        return false;
8167    }
8168
8169    void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
8170            final int oldStatus, final int level) {
8171        boolean doWrite = false;
8172        Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
8173        m.arg1 = onBattery ? 1 : 0;
8174        mHandler.sendMessage(m);
8175
8176        final long uptime = mSecUptime * 1000;
8177        final long realtime = mSecRealtime * 1000;
8178        final boolean screenOn = mScreenState == Display.STATE_ON;
8179        if (onBattery) {
8180            // We will reset our status if we are unplugging after the
8181            // battery was last full, or the level is at 100, or
8182            // we have gone through a significant charge (from a very low
8183            // level to a now very high level).
8184            boolean reset = false;
8185            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
8186                    || level >= 90
8187                    || (mDischargeCurrentLevel < 20 && level >= 80)
8188                    || (getHighDischargeAmountSinceCharge() >= 200
8189                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
8190                Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
8191                        + " dischargeLevel=" + mDischargeCurrentLevel
8192                        + " lowAmount=" + getLowDischargeAmountSinceCharge()
8193                        + " highAmount=" + getHighDischargeAmountSinceCharge());
8194                // Before we write, collect a snapshot of the final aggregated
8195                // stats to be reported in the next checkin.  Only do this if we have
8196                // a sufficient amount of data to make it interesting.
8197                if (getLowDischargeAmountSinceCharge() >= 20) {
8198                    final Parcel parcel = Parcel.obtain();
8199                    writeSummaryToParcel(parcel, true);
8200                    BackgroundThread.getHandler().post(new Runnable() {
8201                        @Override public void run() {
8202                            synchronized (mCheckinFile) {
8203                                FileOutputStream stream = null;
8204                                try {
8205                                    stream = mCheckinFile.startWrite();
8206                                    stream.write(parcel.marshall());
8207                                    stream.flush();
8208                                    FileUtils.sync(stream);
8209                                    stream.close();
8210                                    mCheckinFile.finishWrite(stream);
8211                                } catch (IOException e) {
8212                                    Slog.w("BatteryStats",
8213                                            "Error writing checkin battery statistics", e);
8214                                    mCheckinFile.failWrite(stream);
8215                                } finally {
8216                                    parcel.recycle();
8217                                }
8218                            }
8219                        }
8220                    });
8221                }
8222                doWrite = true;
8223                resetAllStatsLocked();
8224                mDischargeStartLevel = level;
8225                reset = true;
8226                mDischargeStepTracker.init();
8227            }
8228            if (mCharging) {
8229                setChargingLocked(false);
8230            }
8231            mLastChargingStateLevel = level;
8232            mOnBattery = mOnBatteryInternal = true;
8233            mLastDischargeStepLevel = level;
8234            mMinDischargeStepLevel = level;
8235            mDischargeStepTracker.clearTime();
8236            mDailyDischargeStepTracker.clearTime();
8237            mInitStepMode = mCurStepMode;
8238            mModStepMode = 0;
8239            pullPendingStateUpdatesLocked();
8240            mHistoryCur.batteryLevel = (byte)level;
8241            mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8242            if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
8243                    + Integer.toHexString(mHistoryCur.states));
8244            if (reset) {
8245                mRecordingHistory = true;
8246                startRecordingHistory(mSecRealtime, mSecUptime, reset);
8247            }
8248            addHistoryRecordLocked(mSecRealtime, mSecUptime);
8249            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
8250            if (screenOn) {
8251                mDischargeScreenOnUnplugLevel = level;
8252                mDischargeScreenOffUnplugLevel = 0;
8253            } else {
8254                mDischargeScreenOnUnplugLevel = 0;
8255                mDischargeScreenOffUnplugLevel = level;
8256            }
8257            mDischargeAmountScreenOn = 0;
8258            mDischargeAmountScreenOff = 0;
8259            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
8260        } else {
8261            mLastChargingStateLevel = level;
8262            mOnBattery = mOnBatteryInternal = false;
8263            pullPendingStateUpdatesLocked();
8264            mHistoryCur.batteryLevel = (byte)level;
8265            mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8266            if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
8267                    + Integer.toHexString(mHistoryCur.states));
8268            addHistoryRecordLocked(mSecRealtime, mSecUptime);
8269            mDischargeCurrentLevel = mDischargePlugLevel = level;
8270            if (level < mDischargeUnplugLevel) {
8271                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
8272                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
8273            }
8274            updateDischargeScreenLevelsLocked(screenOn, screenOn);
8275            updateTimeBasesLocked(false, !screenOn, uptime, realtime);
8276            mChargeStepTracker.init();
8277            mLastChargeStepLevel = level;
8278            mMaxChargeStepLevel = level;
8279            mInitStepMode = mCurStepMode;
8280            mModStepMode = 0;
8281        }
8282        if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
8283            if (mFile != null) {
8284                writeAsyncLocked();
8285            }
8286        }
8287    }
8288
8289    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
8290            boolean reset) {
8291        mRecordingHistory = true;
8292        mHistoryCur.currentTime = System.currentTimeMillis();
8293        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
8294                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
8295                mHistoryCur);
8296        mHistoryCur.currentTime = 0;
8297        if (reset) {
8298            initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
8299        }
8300    }
8301
8302    private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
8303            final long uptimeMs) {
8304        if (mRecordingHistory) {
8305            mHistoryCur.currentTime = currentTime;
8306            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
8307                    mHistoryCur);
8308            mHistoryCur.currentTime = 0;
8309        }
8310    }
8311
8312    private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
8313        if (mRecordingHistory) {
8314            mHistoryCur.currentTime = System.currentTimeMillis();
8315            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
8316                    mHistoryCur);
8317            mHistoryCur.currentTime = 0;
8318        }
8319    }
8320
8321    private void scheduleSyncExternalStatsLocked(String reason) {
8322        if (mExternalSync != null) {
8323            mExternalSync.scheduleSync(reason);
8324        }
8325    }
8326
8327    private void scheduleSyncExternalWifiStatsLocked(String reason) {
8328        if (mExternalSync != null) {
8329            mExternalSync.scheduleWifiSync(reason);
8330        }
8331    }
8332
8333    // This should probably be exposed in the API, though it's not critical
8334    public static final int BATTERY_PLUGGED_NONE = 0;
8335
8336    public void setBatteryStateLocked(int status, int health, int plugType, int level,
8337            int temp, int volt) {
8338        final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
8339        final long uptime = SystemClock.uptimeMillis();
8340        final long elapsedRealtime = SystemClock.elapsedRealtime();
8341        if (!mHaveBatteryLevel) {
8342            mHaveBatteryLevel = true;
8343            // We start out assuming that the device is plugged in (not
8344            // on battery).  If our first report is now that we are indeed
8345            // plugged in, then twiddle our state to correctly reflect that
8346            // since we won't be going through the full setOnBattery().
8347            if (onBattery == mOnBattery) {
8348                if (onBattery) {
8349                    mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8350                } else {
8351                    mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8352                }
8353            }
8354            // Always start out assuming charging, that will be updated later.
8355            mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
8356            mHistoryCur.batteryStatus = (byte)status;
8357            mHistoryCur.batteryLevel = (byte)level;
8358            mMaxChargeStepLevel = mMinDischargeStepLevel =
8359                    mLastChargeStepLevel = mLastDischargeStepLevel = level;
8360            mLastChargingStateLevel = level;
8361        } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
8362            recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
8363        }
8364        int oldStatus = mHistoryCur.batteryStatus;
8365        if (onBattery) {
8366            mDischargeCurrentLevel = level;
8367            if (!mRecordingHistory) {
8368                mRecordingHistory = true;
8369                startRecordingHistory(elapsedRealtime, uptime, true);
8370            }
8371        } else if (level < 96) {
8372            if (!mRecordingHistory) {
8373                mRecordingHistory = true;
8374                startRecordingHistory(elapsedRealtime, uptime, true);
8375            }
8376        }
8377        mCurrentBatteryLevel = level;
8378        if (mDischargePlugLevel < 0) {
8379            mDischargePlugLevel = level;
8380        }
8381        if (onBattery != mOnBattery) {
8382            mHistoryCur.batteryLevel = (byte)level;
8383            mHistoryCur.batteryStatus = (byte)status;
8384            mHistoryCur.batteryHealth = (byte)health;
8385            mHistoryCur.batteryPlugType = (byte)plugType;
8386            mHistoryCur.batteryTemperature = (short)temp;
8387            mHistoryCur.batteryVoltage = (char)volt;
8388            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
8389        } else {
8390            boolean changed = false;
8391            if (mHistoryCur.batteryLevel != level) {
8392                mHistoryCur.batteryLevel = (byte)level;
8393                changed = true;
8394
8395                // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
8396                // which will pull external stats.
8397                scheduleSyncExternalStatsLocked("battery-level");
8398            }
8399            if (mHistoryCur.batteryStatus != status) {
8400                mHistoryCur.batteryStatus = (byte)status;
8401                changed = true;
8402            }
8403            if (mHistoryCur.batteryHealth != health) {
8404                mHistoryCur.batteryHealth = (byte)health;
8405                changed = true;
8406            }
8407            if (mHistoryCur.batteryPlugType != plugType) {
8408                mHistoryCur.batteryPlugType = (byte)plugType;
8409                changed = true;
8410            }
8411            if (temp >= (mHistoryCur.batteryTemperature+10)
8412                    || temp <= (mHistoryCur.batteryTemperature-10)) {
8413                mHistoryCur.batteryTemperature = (short)temp;
8414                changed = true;
8415            }
8416            if (volt > (mHistoryCur.batteryVoltage+20)
8417                    || volt < (mHistoryCur.batteryVoltage-20)) {
8418                mHistoryCur.batteryVoltage = (char)volt;
8419                changed = true;
8420            }
8421            long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
8422                    | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
8423                    | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
8424            if (onBattery) {
8425                changed |= setChargingLocked(false);
8426                if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
8427                    mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
8428                            modeBits, elapsedRealtime);
8429                    mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
8430                            modeBits, elapsedRealtime);
8431                    mLastDischargeStepLevel = level;
8432                    mMinDischargeStepLevel = level;
8433                    mInitStepMode = mCurStepMode;
8434                    mModStepMode = 0;
8435                }
8436            } else {
8437                if (level >= 90) {
8438                    // If the battery level is at least 90%, always consider the device to be
8439                    // charging even if it happens to go down a level.
8440                    changed |= setChargingLocked(true);
8441                    mLastChargeStepLevel = level;
8442                } if (!mCharging) {
8443                    if (mLastChargeStepLevel < level) {
8444                        // We have not reporting that we are charging, but the level has now
8445                        // gone up, so consider the state to be charging.
8446                        changed |= setChargingLocked(true);
8447                        mLastChargeStepLevel = level;
8448                    }
8449                } else {
8450                    if (mLastChargeStepLevel > level) {
8451                        // We had reported that the device was charging, but here we are with
8452                        // power connected and the level going down.  Looks like the current
8453                        // power supplied isn't enough, so consider the device to now be
8454                        // discharging.
8455                        changed |= setChargingLocked(false);
8456                        mLastChargeStepLevel = level;
8457                    }
8458                }
8459                if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
8460                    mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
8461                            modeBits, elapsedRealtime);
8462                    mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
8463                            modeBits, elapsedRealtime);
8464                    mLastChargeStepLevel = level;
8465                    mMaxChargeStepLevel = level;
8466                    mInitStepMode = mCurStepMode;
8467                    mModStepMode = 0;
8468                }
8469            }
8470            if (changed) {
8471                addHistoryRecordLocked(elapsedRealtime, uptime);
8472            }
8473        }
8474        if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
8475            // We don't record history while we are plugged in and fully charged.
8476            // The next time we are unplugged, history will be cleared.
8477            mRecordingHistory = DEBUG;
8478        }
8479    }
8480
8481    public long getAwakeTimeBattery() {
8482        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
8483    }
8484
8485    public long getAwakeTimePlugged() {
8486        return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
8487    }
8488
8489    @Override
8490    public long computeUptime(long curTime, int which) {
8491        switch (which) {
8492            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
8493            case STATS_CURRENT: return (curTime-mUptimeStart);
8494            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
8495        }
8496        return 0;
8497    }
8498
8499    @Override
8500    public long computeRealtime(long curTime, int which) {
8501        switch (which) {
8502            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
8503            case STATS_CURRENT: return (curTime-mRealtimeStart);
8504            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
8505        }
8506        return 0;
8507    }
8508
8509    @Override
8510    public long computeBatteryUptime(long curTime, int which) {
8511        return mOnBatteryTimeBase.computeUptime(curTime, which);
8512    }
8513
8514    @Override
8515    public long computeBatteryRealtime(long curTime, int which) {
8516        return mOnBatteryTimeBase.computeRealtime(curTime, which);
8517    }
8518
8519    @Override
8520    public long computeBatteryScreenOffUptime(long curTime, int which) {
8521        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
8522    }
8523
8524    @Override
8525    public long computeBatteryScreenOffRealtime(long curTime, int which) {
8526        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
8527    }
8528
8529    private long computeTimePerLevel(long[] steps, int numSteps) {
8530        // For now we'll do a simple average across all steps.
8531        if (numSteps <= 0) {
8532            return -1;
8533        }
8534        long total = 0;
8535        for (int i=0; i<numSteps; i++) {
8536            total += steps[i] & STEP_LEVEL_TIME_MASK;
8537        }
8538        return total / numSteps;
8539        /*
8540        long[] buckets = new long[numSteps];
8541        int numBuckets = 0;
8542        int numToAverage = 4;
8543        int i = 0;
8544        while (i < numSteps) {
8545            long totalTime = 0;
8546            int num = 0;
8547            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
8548                totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
8549                num++;
8550            }
8551            buckets[numBuckets] = totalTime / num;
8552            numBuckets++;
8553            numToAverage *= 2;
8554            i += num;
8555        }
8556        if (numBuckets < 1) {
8557            return -1;
8558        }
8559        long averageTime = buckets[numBuckets-1];
8560        for (i=numBuckets-2; i>=0; i--) {
8561            averageTime = (averageTime + buckets[i]) / 2;
8562        }
8563        return averageTime;
8564        */
8565    }
8566
8567    @Override
8568    public long computeBatteryTimeRemaining(long curTime) {
8569        if (!mOnBattery) {
8570            return -1;
8571        }
8572        /* Simple implementation just looks at the average discharge per level across the
8573           entire sample period.
8574        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
8575        if (discharge < 2) {
8576            return -1;
8577        }
8578        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
8579        if (duration < 1000*1000) {
8580            return -1;
8581        }
8582        long usPerLevel = duration/discharge;
8583        return usPerLevel * mCurrentBatteryLevel;
8584        */
8585        if (mDischargeStepTracker.mNumStepDurations < 1) {
8586            return -1;
8587        }
8588        long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
8589        if (msPerLevel <= 0) {
8590            return -1;
8591        }
8592        return (msPerLevel * mCurrentBatteryLevel) * 1000;
8593    }
8594
8595    @Override
8596    public LevelStepTracker getDischargeLevelStepTracker() {
8597        return mDischargeStepTracker;
8598    }
8599
8600    @Override
8601    public LevelStepTracker getDailyDischargeLevelStepTracker() {
8602        return mDailyDischargeStepTracker;
8603    }
8604
8605    @Override
8606    public long computeChargeTimeRemaining(long curTime) {
8607        if (mOnBattery) {
8608            // Not yet working.
8609            return -1;
8610        }
8611        /* Broken
8612        int curLevel = mCurrentBatteryLevel;
8613        int plugLevel = mDischargePlugLevel;
8614        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
8615            return -1;
8616        }
8617        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
8618        if (duration < 1000*1000) {
8619            return -1;
8620        }
8621        long usPerLevel = duration/(curLevel-plugLevel);
8622        return usPerLevel * (100-curLevel);
8623        */
8624        if (mChargeStepTracker.mNumStepDurations < 1) {
8625            return -1;
8626        }
8627        long msPerLevel = mChargeStepTracker.computeTimePerLevel();
8628        if (msPerLevel <= 0) {
8629            return -1;
8630        }
8631        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
8632    }
8633
8634    @Override
8635    public LevelStepTracker getChargeLevelStepTracker() {
8636        return mChargeStepTracker;
8637    }
8638
8639    @Override
8640    public LevelStepTracker getDailyChargeLevelStepTracker() {
8641        return mDailyChargeStepTracker;
8642    }
8643
8644    @Override
8645    public ArrayList<PackageChange> getDailyPackageChanges() {
8646        return mDailyPackageChanges;
8647    }
8648
8649    long getBatteryUptimeLocked() {
8650        return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
8651    }
8652
8653    @Override
8654    public long getBatteryUptime(long curTime) {
8655        return mOnBatteryTimeBase.getUptime(curTime);
8656    }
8657
8658    @Override
8659    public long getBatteryRealtime(long curTime) {
8660        return mOnBatteryTimeBase.getRealtime(curTime);
8661    }
8662
8663    @Override
8664    public int getDischargeStartLevel() {
8665        synchronized(this) {
8666            return getDischargeStartLevelLocked();
8667        }
8668    }
8669
8670    public int getDischargeStartLevelLocked() {
8671            return mDischargeUnplugLevel;
8672    }
8673
8674    @Override
8675    public int getDischargeCurrentLevel() {
8676        synchronized(this) {
8677            return getDischargeCurrentLevelLocked();
8678        }
8679    }
8680
8681    public int getDischargeCurrentLevelLocked() {
8682        return mDischargeCurrentLevel;
8683    }
8684
8685    @Override
8686    public int getLowDischargeAmountSinceCharge() {
8687        synchronized(this) {
8688            int val = mLowDischargeAmountSinceCharge;
8689            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
8690                val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
8691            }
8692            return val;
8693        }
8694    }
8695
8696    @Override
8697    public int getHighDischargeAmountSinceCharge() {
8698        synchronized(this) {
8699            int val = mHighDischargeAmountSinceCharge;
8700            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
8701                val += mDischargeUnplugLevel-mDischargeCurrentLevel;
8702            }
8703            return val;
8704        }
8705    }
8706
8707    @Override
8708    public int getDischargeAmount(int which) {
8709        int dischargeAmount = which == STATS_SINCE_CHARGED
8710                ? getHighDischargeAmountSinceCharge()
8711                : (getDischargeStartLevel() - getDischargeCurrentLevel());
8712        if (dischargeAmount < 0) {
8713            dischargeAmount = 0;
8714        }
8715        return dischargeAmount;
8716    }
8717
8718    public int getDischargeAmountScreenOn() {
8719        synchronized(this) {
8720            int val = mDischargeAmountScreenOn;
8721            if (mOnBattery && mScreenState == Display.STATE_ON
8722                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
8723                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
8724            }
8725            return val;
8726        }
8727    }
8728
8729    public int getDischargeAmountScreenOnSinceCharge() {
8730        synchronized(this) {
8731            int val = mDischargeAmountScreenOnSinceCharge;
8732            if (mOnBattery && mScreenState == Display.STATE_ON
8733                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
8734                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
8735            }
8736            return val;
8737        }
8738    }
8739
8740    public int getDischargeAmountScreenOff() {
8741        synchronized(this) {
8742            int val = mDischargeAmountScreenOff;
8743            if (mOnBattery && mScreenState != Display.STATE_ON
8744                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
8745                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
8746            }
8747            return val;
8748        }
8749    }
8750
8751    public int getDischargeAmountScreenOffSinceCharge() {
8752        synchronized(this) {
8753            int val = mDischargeAmountScreenOffSinceCharge;
8754            if (mOnBattery && mScreenState != Display.STATE_ON
8755                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
8756                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
8757            }
8758            return val;
8759        }
8760    }
8761
8762    @Override
8763    public int getCpuSpeedSteps() {
8764        return sNumSpeedSteps;
8765    }
8766
8767    /**
8768     * Retrieve the statistics object for a particular uid, creating if needed.
8769     */
8770    public Uid getUidStatsLocked(int uid) {
8771        Uid u = mUidStats.get(uid);
8772        if (u == null) {
8773            u = new Uid(uid);
8774            mUidStats.put(uid, u);
8775        }
8776        return u;
8777    }
8778
8779    /**
8780     * Remove the statistics object for a particular uid.
8781     */
8782    public void removeUidStatsLocked(int uid) {
8783        mKernelUidCpuTimeReader.removeUid(uid);
8784        mUidStats.remove(uid);
8785    }
8786
8787    /**
8788     * Retrieve the statistics object for a particular process, creating
8789     * if needed.
8790     */
8791    public Uid.Proc getProcessStatsLocked(int uid, String name) {
8792        uid = mapUid(uid);
8793        Uid u = getUidStatsLocked(uid);
8794        return u.getProcessStatsLocked(name);
8795    }
8796
8797    /**
8798     * Retrieve the statistics object for a particular process, creating
8799     * if needed.
8800     */
8801    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
8802        uid = mapUid(uid);
8803        Uid u = getUidStatsLocked(uid);
8804        return u.getPackageStatsLocked(pkg);
8805    }
8806
8807    /**
8808     * Retrieve the statistics object for a particular service, creating
8809     * if needed.
8810     */
8811    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
8812        uid = mapUid(uid);
8813        Uid u = getUidStatsLocked(uid);
8814        return u.getServiceStatsLocked(pkg, name);
8815    }
8816
8817    public void shutdownLocked() {
8818        recordShutdownLocked(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
8819        writeSyncLocked();
8820        mShuttingDown = true;
8821    }
8822
8823    Parcel mPendingWrite = null;
8824    final ReentrantLock mWriteLock = new ReentrantLock();
8825
8826    public void writeAsyncLocked() {
8827        writeLocked(false);
8828    }
8829
8830    public void writeSyncLocked() {
8831        writeLocked(true);
8832    }
8833
8834    void writeLocked(boolean sync) {
8835        if (mFile == null) {
8836            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
8837            return;
8838        }
8839
8840        if (mShuttingDown) {
8841            return;
8842        }
8843
8844        Parcel out = Parcel.obtain();
8845        writeSummaryToParcel(out, true);
8846        mLastWriteTime = SystemClock.elapsedRealtime();
8847
8848        if (mPendingWrite != null) {
8849            mPendingWrite.recycle();
8850        }
8851        mPendingWrite = out;
8852
8853        if (sync) {
8854            commitPendingDataToDisk();
8855        } else {
8856            BackgroundThread.getHandler().post(new Runnable() {
8857                @Override public void run() {
8858                    commitPendingDataToDisk();
8859                }
8860            });
8861        }
8862    }
8863
8864    public void commitPendingDataToDisk() {
8865        final Parcel next;
8866        synchronized (this) {
8867            next = mPendingWrite;
8868            mPendingWrite = null;
8869            if (next == null) {
8870                return;
8871            }
8872
8873            mWriteLock.lock();
8874        }
8875
8876        try {
8877            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
8878            stream.write(next.marshall());
8879            stream.flush();
8880            FileUtils.sync(stream);
8881            stream.close();
8882            mFile.commit();
8883        } catch (IOException e) {
8884            Slog.w("BatteryStats", "Error writing battery statistics", e);
8885            mFile.rollback();
8886        } finally {
8887            next.recycle();
8888            mWriteLock.unlock();
8889        }
8890    }
8891
8892    public void readLocked() {
8893        if (mDailyFile != null) {
8894            readDailyStatsLocked();
8895        }
8896
8897        if (mFile == null) {
8898            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
8899            return;
8900        }
8901
8902        mUidStats.clear();
8903
8904        try {
8905            File file = mFile.chooseForRead();
8906            if (!file.exists()) {
8907                return;
8908            }
8909            FileInputStream stream = new FileInputStream(file);
8910
8911            byte[] raw = BatteryStatsHelper.readFully(stream);
8912            Parcel in = Parcel.obtain();
8913            in.unmarshall(raw, 0, raw.length);
8914            in.setDataPosition(0);
8915            stream.close();
8916
8917            readSummaryFromParcel(in);
8918        } catch(Exception e) {
8919            Slog.e("BatteryStats", "Error reading battery statistics", e);
8920            resetAllStatsLocked();
8921        }
8922
8923        mEndPlatformVersion = Build.ID;
8924
8925        if (mHistoryBuffer.dataPosition() > 0) {
8926            mRecordingHistory = true;
8927            final long elapsedRealtime = SystemClock.elapsedRealtime();
8928            final long uptime = SystemClock.uptimeMillis();
8929            if (USE_OLD_HISTORY) {
8930                addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
8931            }
8932            addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
8933            startRecordingHistory(elapsedRealtime, uptime, false);
8934        }
8935
8936        recordDailyStatsIfNeededLocked(false);
8937    }
8938
8939    public int describeContents() {
8940        return 0;
8941    }
8942
8943    void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
8944        final long historyBaseTime = in.readLong();
8945
8946        mHistoryBuffer.setDataSize(0);
8947        mHistoryBuffer.setDataPosition(0);
8948        mHistoryTagPool.clear();
8949        mNextHistoryTagIdx = 0;
8950        mNumHistoryTagChars = 0;
8951
8952        int numTags = in.readInt();
8953        for (int i=0; i<numTags; i++) {
8954            int idx = in.readInt();
8955            String str = in.readString();
8956            if (str == null) {
8957                throw new ParcelFormatException("null history tag string");
8958            }
8959            int uid = in.readInt();
8960            HistoryTag tag = new HistoryTag();
8961            tag.string = str;
8962            tag.uid = uid;
8963            tag.poolIdx = idx;
8964            mHistoryTagPool.put(tag, idx);
8965            if (idx >= mNextHistoryTagIdx) {
8966                mNextHistoryTagIdx = idx+1;
8967            }
8968            mNumHistoryTagChars += tag.string.length() + 1;
8969        }
8970
8971        int bufSize = in.readInt();
8972        int curPos = in.dataPosition();
8973        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
8974            throw new ParcelFormatException("File corrupt: history data buffer too large " +
8975                    bufSize);
8976        } else if ((bufSize&~3) != bufSize) {
8977            throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
8978                    bufSize);
8979        } else {
8980            if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
8981                    + " bytes at " + curPos);
8982            mHistoryBuffer.appendFrom(in, curPos, bufSize);
8983            in.setDataPosition(curPos + bufSize);
8984        }
8985
8986        if (andOldHistory) {
8987            readOldHistory(in);
8988        }
8989
8990        if (DEBUG_HISTORY) {
8991            StringBuilder sb = new StringBuilder(128);
8992            sb.append("****************** OLD mHistoryBaseTime: ");
8993            TimeUtils.formatDuration(mHistoryBaseTime, sb);
8994            Slog.i(TAG, sb.toString());
8995        }
8996        mHistoryBaseTime = historyBaseTime;
8997        if (DEBUG_HISTORY) {
8998            StringBuilder sb = new StringBuilder(128);
8999            sb.append("****************** NEW mHistoryBaseTime: ");
9000            TimeUtils.formatDuration(mHistoryBaseTime, sb);
9001            Slog.i(TAG, sb.toString());
9002        }
9003
9004        // We are just arbitrarily going to insert 1 minute from the sample of
9005        // the last run until samples in this run.
9006        if (mHistoryBaseTime > 0) {
9007            long oldnow = SystemClock.elapsedRealtime();
9008            mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
9009            if (DEBUG_HISTORY) {
9010                StringBuilder sb = new StringBuilder(128);
9011                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
9012                TimeUtils.formatDuration(mHistoryBaseTime, sb);
9013                Slog.i(TAG, sb.toString());
9014            }
9015        }
9016    }
9017
9018    void readOldHistory(Parcel in) {
9019        if (!USE_OLD_HISTORY) {
9020            return;
9021        }
9022        mHistory = mHistoryEnd = mHistoryCache = null;
9023        long time;
9024        while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
9025            HistoryItem rec = new HistoryItem(time, in);
9026            addHistoryRecordLocked(rec);
9027        }
9028    }
9029
9030    void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
9031        if (DEBUG_HISTORY) {
9032            StringBuilder sb = new StringBuilder(128);
9033            sb.append("****************** WRITING mHistoryBaseTime: ");
9034            TimeUtils.formatDuration(mHistoryBaseTime, sb);
9035            sb.append(" mLastHistoryElapsedRealtime: ");
9036            TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
9037            Slog.i(TAG, sb.toString());
9038        }
9039        out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
9040        if (!inclData) {
9041            out.writeInt(0);
9042            out.writeInt(0);
9043            return;
9044        }
9045        out.writeInt(mHistoryTagPool.size());
9046        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
9047            HistoryTag tag = ent.getKey();
9048            out.writeInt(ent.getValue());
9049            out.writeString(tag.string);
9050            out.writeInt(tag.uid);
9051        }
9052        out.writeInt(mHistoryBuffer.dataSize());
9053        if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
9054                + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
9055        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
9056
9057        if (andOldHistory) {
9058            writeOldHistory(out);
9059        }
9060    }
9061
9062    void writeOldHistory(Parcel out) {
9063        if (!USE_OLD_HISTORY) {
9064            return;
9065        }
9066        HistoryItem rec = mHistory;
9067        while (rec != null) {
9068            if (rec.time >= 0) rec.writeToParcel(out, 0);
9069            rec = rec.next;
9070        }
9071        out.writeLong(-1);
9072    }
9073
9074    public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
9075        final int version = in.readInt();
9076        if (version != VERSION) {
9077            Slog.w("BatteryStats", "readFromParcel: version got " + version
9078                + ", expected " + VERSION + "; erasing old stats");
9079            return;
9080        }
9081
9082        readHistory(in, true);
9083
9084        mStartCount = in.readInt();
9085        mUptime = in.readLong();
9086        mRealtime = in.readLong();
9087        mStartClockTime = in.readLong();
9088        mStartPlatformVersion = in.readString();
9089        mEndPlatformVersion = in.readString();
9090        mOnBatteryTimeBase.readSummaryFromParcel(in);
9091        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
9092        mDischargeUnplugLevel = in.readInt();
9093        mDischargePlugLevel = in.readInt();
9094        mDischargeCurrentLevel = in.readInt();
9095        mCurrentBatteryLevel = in.readInt();
9096        mLowDischargeAmountSinceCharge = in.readInt();
9097        mHighDischargeAmountSinceCharge = in.readInt();
9098        mDischargeAmountScreenOnSinceCharge = in.readInt();
9099        mDischargeAmountScreenOffSinceCharge = in.readInt();
9100        mDischargeStepTracker.readFromParcel(in);
9101        mChargeStepTracker.readFromParcel(in);
9102        mDailyDischargeStepTracker.readFromParcel(in);
9103        mDailyChargeStepTracker.readFromParcel(in);
9104        int NPKG = in.readInt();
9105        if (NPKG > 0) {
9106            mDailyPackageChanges = new ArrayList<>(NPKG);
9107            while (NPKG > 0) {
9108                NPKG--;
9109                PackageChange pc = new PackageChange();
9110                pc.mPackageName = in.readString();
9111                pc.mUpdate = in.readInt() != 0;
9112                pc.mVersionCode = in.readInt();
9113                mDailyPackageChanges.add(pc);
9114            }
9115        } else {
9116            mDailyPackageChanges = null;
9117        }
9118        mDailyStartTime = in.readLong();
9119        mNextMinDailyDeadline = in.readLong();
9120        mNextMaxDailyDeadline = in.readLong();
9121
9122        mStartCount++;
9123
9124        mScreenState = Display.STATE_UNKNOWN;
9125        mScreenOnTimer.readSummaryFromParcelLocked(in);
9126        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9127            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
9128        }
9129        mInteractive = false;
9130        mInteractiveTimer.readSummaryFromParcelLocked(in);
9131        mPhoneOn = false;
9132        mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
9133        mDeviceIdleModeEnabledTimer.readSummaryFromParcelLocked(in);
9134        mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
9135        mPhoneOnTimer.readSummaryFromParcelLocked(in);
9136        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9137            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
9138        }
9139        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
9140        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9141            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
9142        }
9143        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9144            mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
9145            mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
9146        }
9147        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9148        mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
9149        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
9150        mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
9151        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
9152        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
9153        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9154        mWifiOn = false;
9155        mWifiOnTimer.readSummaryFromParcelLocked(in);
9156        mGlobalWifiRunning = false;
9157        mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
9158        for (int i=0; i<NUM_WIFI_STATES; i++) {
9159            mWifiStateTimer[i].readSummaryFromParcelLocked(in);
9160        }
9161        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9162            mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
9163        }
9164        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9165            mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
9166        }
9167        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9168            mBluetoothActivityCounters[i].readSummaryFromParcelLocked(in);
9169        }
9170        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9171            mWifiActivityCounters[i].readSummaryFromParcelLocked(in);
9172        }
9173
9174        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
9175        mFlashlightOnNesting = 0;
9176        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
9177        mCameraOnNesting = 0;
9178        mCameraOnTimer.readSummaryFromParcelLocked(in);
9179
9180        int NKW = in.readInt();
9181        if (NKW > 10000) {
9182            throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
9183        }
9184        for (int ikw = 0; ikw < NKW; ikw++) {
9185            if (in.readInt() != 0) {
9186                String kwltName = in.readString();
9187                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
9188            }
9189        }
9190
9191        int NWR = in.readInt();
9192        if (NWR > 10000) {
9193            throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
9194        }
9195        for (int iwr = 0; iwr < NWR; iwr++) {
9196            if (in.readInt() != 0) {
9197                String reasonName = in.readString();
9198                getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
9199            }
9200        }
9201
9202        sNumSpeedSteps = in.readInt();
9203        if (sNumSpeedSteps < 0 || sNumSpeedSteps > 100) {
9204            throw new ParcelFormatException("Bad speed steps in data: " + sNumSpeedSteps);
9205        }
9206
9207        final int NU = in.readInt();
9208        if (NU > 10000) {
9209            throw new ParcelFormatException("File corrupt: too many uids " + NU);
9210        }
9211        for (int iu = 0; iu < NU; iu++) {
9212            int uid = in.readInt();
9213            Uid u = new Uid(uid);
9214            mUidStats.put(uid, u);
9215
9216            u.mWifiRunning = false;
9217            if (in.readInt() != 0) {
9218                u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
9219            }
9220            u.mFullWifiLockOut = false;
9221            if (in.readInt() != 0) {
9222                u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
9223            }
9224            u.mWifiScanStarted = false;
9225            if (in.readInt() != 0) {
9226                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
9227            }
9228            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
9229            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9230                if (in.readInt() != 0) {
9231                    u.makeWifiBatchedScanBin(i, null);
9232                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
9233                }
9234            }
9235            u.mWifiMulticastEnabled = false;
9236            if (in.readInt() != 0) {
9237                u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
9238            }
9239            if (in.readInt() != 0) {
9240                u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9241            }
9242            if (in.readInt() != 0) {
9243                u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9244            }
9245            if (in.readInt() != 0) {
9246                u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9247            }
9248            if (in.readInt() != 0) {
9249                u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9250            }
9251            if (in.readInt() != 0) {
9252                u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
9253            }
9254            u.mProcessState = Uid.PROCESS_STATE_NONE;
9255            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
9256                if (in.readInt() != 0) {
9257                    u.makeProcessState(i, null);
9258                    u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
9259                }
9260            }
9261            if (in.readInt() != 0) {
9262                u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
9263            }
9264
9265            if (in.readInt() != 0) {
9266                if (u.mUserActivityCounters == null) {
9267                    u.initUserActivityLocked();
9268                }
9269                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
9270                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
9271                }
9272            }
9273
9274            if (in.readInt() != 0) {
9275                if (u.mNetworkByteActivityCounters == null) {
9276                    u.initNetworkActivityLocked();
9277                }
9278                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9279                    u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
9280                    u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
9281                }
9282                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
9283                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
9284            }
9285
9286            u.mUserCpuTime.readSummaryFromParcelLocked(in);
9287            u.mSystemCpuTime.readSummaryFromParcelLocked(in);
9288            u.mCpuPower.readSummaryFromParcelLocked(in);
9289
9290            int NSB = in.readInt();
9291            if (NSB > 100) {
9292                throw new ParcelFormatException("File corrupt: too many speed bins " + NSB);
9293            }
9294
9295            u.mSpeedBins = new LongSamplingCounter[NSB];
9296            for (int i=0; i<NSB; i++) {
9297                if (in.readInt() != 0) {
9298                    u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
9299                    u.mSpeedBins[i].readSummaryFromParcelLocked(in);
9300                }
9301            }
9302
9303            int NW = in.readInt();
9304            if (NW > 100) {
9305                throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
9306            }
9307            for (int iw = 0; iw < NW; iw++) {
9308                String wlName = in.readString();
9309                u.readWakeSummaryFromParcelLocked(wlName, in);
9310            }
9311
9312            int NS = in.readInt();
9313            if (NS > 100) {
9314                throw new ParcelFormatException("File corrupt: too many syncs " + NS);
9315            }
9316            for (int is = 0; is < NS; is++) {
9317                String name = in.readString();
9318                u.readSyncSummaryFromParcelLocked(name, in);
9319            }
9320
9321            int NJ = in.readInt();
9322            if (NJ > 100) {
9323                throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
9324            }
9325            for (int ij = 0; ij < NJ; ij++) {
9326                String name = in.readString();
9327                u.readJobSummaryFromParcelLocked(name, in);
9328            }
9329
9330            int NP = in.readInt();
9331            if (NP > 1000) {
9332                throw new ParcelFormatException("File corrupt: too many sensors " + NP);
9333            }
9334            for (int is = 0; is < NP; is++) {
9335                int seNumber = in.readInt();
9336                if (in.readInt() != 0) {
9337                    u.getSensorTimerLocked(seNumber, true)
9338                            .readSummaryFromParcelLocked(in);
9339                }
9340            }
9341
9342            NP = in.readInt();
9343            if (NP > 1000) {
9344                throw new ParcelFormatException("File corrupt: too many processes " + NP);
9345            }
9346            for (int ip = 0; ip < NP; ip++) {
9347                String procName = in.readString();
9348                Uid.Proc p = u.getProcessStatsLocked(procName);
9349                p.mUserTime = p.mLoadedUserTime = in.readLong();
9350                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
9351                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
9352                p.mStarts = p.mLoadedStarts = in.readInt();
9353                p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
9354                p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
9355                p.readExcessivePowerFromParcelLocked(in);
9356            }
9357
9358            NP = in.readInt();
9359            if (NP > 10000) {
9360                throw new ParcelFormatException("File corrupt: too many packages " + NP);
9361            }
9362            for (int ip = 0; ip < NP; ip++) {
9363                String pkgName = in.readString();
9364                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
9365                final int NWA = in.readInt();
9366                if (NWA > 1000) {
9367                    throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
9368                }
9369                p.mWakeupAlarms.clear();
9370                for (int iwa=0; iwa<NWA; iwa++) {
9371                    String tag = in.readString();
9372                    Counter c = new Counter(mOnBatteryTimeBase);
9373                    c.readSummaryFromParcelLocked(in);
9374                    p.mWakeupAlarms.put(tag, c);
9375                }
9376                NS = in.readInt();
9377                if (NS > 1000) {
9378                    throw new ParcelFormatException("File corrupt: too many services " + NS);
9379                }
9380                for (int is = 0; is < NS; is++) {
9381                    String servName = in.readString();
9382                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
9383                    s.mStartTime = s.mLoadedStartTime = in.readLong();
9384                    s.mStarts = s.mLoadedStarts = in.readInt();
9385                    s.mLaunches = s.mLoadedLaunches = in.readInt();
9386                }
9387            }
9388        }
9389    }
9390
9391    /**
9392     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
9393     * disk.  This format does not allow a lossless round-trip.
9394     *
9395     * @param out the Parcel to be written to.
9396     */
9397    public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
9398        pullPendingStateUpdatesLocked();
9399
9400        // Pull the clock time.  This may update the time and make a new history entry
9401        // if we had originally pulled a time before the RTC was set.
9402        long startClockTime = getStartClockTime();
9403
9404        final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
9405        final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
9406
9407        out.writeInt(VERSION);
9408
9409        writeHistory(out, inclHistory, true);
9410
9411        out.writeInt(mStartCount);
9412        out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
9413        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
9414        out.writeLong(startClockTime);
9415        out.writeString(mStartPlatformVersion);
9416        out.writeString(mEndPlatformVersion);
9417        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
9418        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
9419        out.writeInt(mDischargeUnplugLevel);
9420        out.writeInt(mDischargePlugLevel);
9421        out.writeInt(mDischargeCurrentLevel);
9422        out.writeInt(mCurrentBatteryLevel);
9423        out.writeInt(getLowDischargeAmountSinceCharge());
9424        out.writeInt(getHighDischargeAmountSinceCharge());
9425        out.writeInt(getDischargeAmountScreenOnSinceCharge());
9426        out.writeInt(getDischargeAmountScreenOffSinceCharge());
9427        mDischargeStepTracker.writeToParcel(out);
9428        mChargeStepTracker.writeToParcel(out);
9429        mDailyDischargeStepTracker.writeToParcel(out);
9430        mDailyChargeStepTracker.writeToParcel(out);
9431        if (mDailyPackageChanges != null) {
9432            final int NPKG = mDailyPackageChanges.size();
9433            out.writeInt(NPKG);
9434            for (int i=0; i<NPKG; i++) {
9435                PackageChange pc = mDailyPackageChanges.get(i);
9436                out.writeString(pc.mPackageName);
9437                out.writeInt(pc.mUpdate ? 1 : 0);
9438                out.writeInt(pc.mVersionCode);
9439            }
9440        } else {
9441            out.writeInt(0);
9442        }
9443        out.writeLong(mDailyStartTime);
9444        out.writeLong(mNextMinDailyDeadline);
9445        out.writeLong(mNextMaxDailyDeadline);
9446
9447        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9448        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9449            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9450        }
9451        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9452        mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9453        mDeviceIdleModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9454        mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9455        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9456        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9457            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9458        }
9459        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9460        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9461            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9462        }
9463        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9464            mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
9465            mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
9466        }
9467        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9468        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9469        mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
9470        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
9471        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
9472        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9473        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9474        for (int i=0; i<NUM_WIFI_STATES; i++) {
9475            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9476        }
9477        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9478            mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9479        }
9480        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9481            mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9482        }
9483        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9484            mBluetoothActivityCounters[i].writeSummaryFromParcelLocked(out);
9485        }
9486        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9487            mWifiActivityCounters[i].writeSummaryFromParcelLocked(out);
9488        }
9489        out.writeInt(mNumConnectivityChange);
9490        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9491        mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9492
9493        out.writeInt(mKernelWakelockStats.size());
9494        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
9495            Timer kwlt = ent.getValue();
9496            if (kwlt != null) {
9497                out.writeInt(1);
9498                out.writeString(ent.getKey());
9499                kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9500            } else {
9501                out.writeInt(0);
9502            }
9503        }
9504
9505        out.writeInt(mWakeupReasonStats.size());
9506        for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
9507            SamplingTimer timer = ent.getValue();
9508            if (timer != null) {
9509                out.writeInt(1);
9510                out.writeString(ent.getKey());
9511                timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9512            } else {
9513                out.writeInt(0);
9514            }
9515        }
9516
9517        out.writeInt(sNumSpeedSteps);
9518        final int NU = mUidStats.size();
9519        out.writeInt(NU);
9520        for (int iu = 0; iu < NU; iu++) {
9521            out.writeInt(mUidStats.keyAt(iu));
9522            Uid u = mUidStats.valueAt(iu);
9523
9524            if (u.mWifiRunningTimer != null) {
9525                out.writeInt(1);
9526                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9527            } else {
9528                out.writeInt(0);
9529            }
9530            if (u.mFullWifiLockTimer != null) {
9531                out.writeInt(1);
9532                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9533            } else {
9534                out.writeInt(0);
9535            }
9536            if (u.mWifiScanTimer != null) {
9537                out.writeInt(1);
9538                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9539            } else {
9540                out.writeInt(0);
9541            }
9542            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9543                if (u.mWifiBatchedScanTimer[i] != null) {
9544                    out.writeInt(1);
9545                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9546                } else {
9547                    out.writeInt(0);
9548                }
9549            }
9550            if (u.mWifiMulticastTimer != null) {
9551                out.writeInt(1);
9552                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9553            } else {
9554                out.writeInt(0);
9555            }
9556            if (u.mAudioTurnedOnTimer != null) {
9557                out.writeInt(1);
9558                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9559            } else {
9560                out.writeInt(0);
9561            }
9562            if (u.mVideoTurnedOnTimer != null) {
9563                out.writeInt(1);
9564                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9565            } else {
9566                out.writeInt(0);
9567            }
9568            if (u.mFlashlightTurnedOnTimer != null) {
9569                out.writeInt(1);
9570                u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9571            } else {
9572                out.writeInt(0);
9573            }
9574            if (u.mCameraTurnedOnTimer != null) {
9575                out.writeInt(1);
9576                u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9577            } else {
9578                out.writeInt(0);
9579            }
9580            if (u.mForegroundActivityTimer != null) {
9581                out.writeInt(1);
9582                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9583            } else {
9584                out.writeInt(0);
9585            }
9586            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
9587                if (u.mProcessStateTimer[i] != null) {
9588                    out.writeInt(1);
9589                    u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9590                } else {
9591                    out.writeInt(0);
9592                }
9593            }
9594            if (u.mVibratorOnTimer != null) {
9595                out.writeInt(1);
9596                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9597            } else {
9598                out.writeInt(0);
9599            }
9600
9601            if (u.mUserActivityCounters == null) {
9602                out.writeInt(0);
9603            } else {
9604                out.writeInt(1);
9605                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
9606                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
9607                }
9608            }
9609
9610            if (u.mNetworkByteActivityCounters == null) {
9611                out.writeInt(0);
9612            } else {
9613                out.writeInt(1);
9614                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9615                    u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
9616                    u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
9617                }
9618                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
9619                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
9620            }
9621
9622            u.mUserCpuTime.writeSummaryFromParcelLocked(out);
9623            u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
9624            u.mCpuPower.writeSummaryFromParcelLocked(out);
9625
9626            out.writeInt(u.mSpeedBins.length);
9627            for (int i = 0; i < u.mSpeedBins.length; i++) {
9628                LongSamplingCounter speedBin = u.mSpeedBins[i];
9629                if (speedBin != null) {
9630                    out.writeInt(1);
9631                    speedBin.writeSummaryFromParcelLocked(out);
9632                } else {
9633                    out.writeInt(0);
9634                }
9635            }
9636
9637            final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
9638            int NW = wakeStats.size();
9639            out.writeInt(NW);
9640            for (int iw=0; iw<NW; iw++) {
9641                out.writeString(wakeStats.keyAt(iw));
9642                Uid.Wakelock wl = wakeStats.valueAt(iw);
9643                if (wl.mTimerFull != null) {
9644                    out.writeInt(1);
9645                    wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9646                } else {
9647                    out.writeInt(0);
9648                }
9649                if (wl.mTimerPartial != null) {
9650                    out.writeInt(1);
9651                    wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9652                } else {
9653                    out.writeInt(0);
9654                }
9655                if (wl.mTimerWindow != null) {
9656                    out.writeInt(1);
9657                    wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9658                } else {
9659                    out.writeInt(0);
9660                }
9661                if (wl.mTimerDraw != null) {
9662                    out.writeInt(1);
9663                    wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9664                } else {
9665                    out.writeInt(0);
9666                }
9667            }
9668
9669            final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
9670            int NS = syncStats.size();
9671            out.writeInt(NS);
9672            for (int is=0; is<NS; is++) {
9673                out.writeString(syncStats.keyAt(is));
9674                syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9675            }
9676
9677            final ArrayMap<String, StopwatchTimer> jobStats = u.mJobStats.getMap();
9678            int NJ = jobStats.size();
9679            out.writeInt(NJ);
9680            for (int ij=0; ij<NJ; ij++) {
9681                out.writeString(jobStats.keyAt(ij));
9682                jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9683            }
9684
9685            int NSE = u.mSensorStats.size();
9686            out.writeInt(NSE);
9687            for (int ise=0; ise<NSE; ise++) {
9688                out.writeInt(u.mSensorStats.keyAt(ise));
9689                Uid.Sensor se = u.mSensorStats.valueAt(ise);
9690                if (se.mTimer != null) {
9691                    out.writeInt(1);
9692                    se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9693                } else {
9694                    out.writeInt(0);
9695                }
9696            }
9697
9698            int NP = u.mProcessStats.size();
9699            out.writeInt(NP);
9700            for (int ip=0; ip<NP; ip++) {
9701                out.writeString(u.mProcessStats.keyAt(ip));
9702                Uid.Proc ps = u.mProcessStats.valueAt(ip);
9703                out.writeLong(ps.mUserTime);
9704                out.writeLong(ps.mSystemTime);
9705                out.writeLong(ps.mForegroundTime);
9706                out.writeInt(ps.mStarts);
9707                out.writeInt(ps.mNumCrashes);
9708                out.writeInt(ps.mNumAnrs);
9709                ps.writeExcessivePowerToParcelLocked(out);
9710            }
9711
9712            NP = u.mPackageStats.size();
9713            out.writeInt(NP);
9714            if (NP > 0) {
9715                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
9716                    : u.mPackageStats.entrySet()) {
9717                    out.writeString(ent.getKey());
9718                    Uid.Pkg ps = ent.getValue();
9719                    final int NWA = ps.mWakeupAlarms.size();
9720                    out.writeInt(NWA);
9721                    for (int iwa=0; iwa<NWA; iwa++) {
9722                        out.writeString(ps.mWakeupAlarms.keyAt(iwa));
9723                        ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
9724                    }
9725                    NS = ps.mServiceStats.size();
9726                    out.writeInt(NS);
9727                    for (int is=0; is<NS; is++) {
9728                        out.writeString(ps.mServiceStats.keyAt(is));
9729                        BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
9730                        long time = ss.getStartTimeToNowLocked(
9731                                mOnBatteryTimeBase.getUptime(NOW_SYS));
9732                        out.writeLong(time);
9733                        out.writeInt(ss.mStarts);
9734                        out.writeInt(ss.mLaunches);
9735                    }
9736                }
9737            }
9738        }
9739    }
9740
9741    public void readFromParcel(Parcel in) {
9742        readFromParcelLocked(in);
9743    }
9744
9745    void readFromParcelLocked(Parcel in) {
9746        int magic = in.readInt();
9747        if (magic != MAGIC) {
9748            throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
9749        }
9750
9751        readHistory(in, false);
9752
9753        mStartCount = in.readInt();
9754        mStartClockTime = in.readLong();
9755        mStartPlatformVersion = in.readString();
9756        mEndPlatformVersion = in.readString();
9757        mUptime = in.readLong();
9758        mUptimeStart = in.readLong();
9759        mRealtime = in.readLong();
9760        mRealtimeStart = in.readLong();
9761        mOnBattery = in.readInt() != 0;
9762        mOnBatteryInternal = false; // we are no longer really running.
9763        mOnBatteryTimeBase.readFromParcel(in);
9764        mOnBatteryScreenOffTimeBase.readFromParcel(in);
9765
9766        mScreenState = Display.STATE_UNKNOWN;
9767        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
9768        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9769            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
9770                    in);
9771        }
9772        mInteractive = false;
9773        mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase, in);
9774        mPhoneOn = false;
9775        mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
9776        mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
9777        mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase, in);
9778        mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
9779        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9780            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
9781                    null, mOnBatteryTimeBase, in);
9782        }
9783        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase, in);
9784        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9785            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
9786                    null, mOnBatteryTimeBase, in);
9787        }
9788        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9789            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9790            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9791        }
9792        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9793        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in);
9794        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase,
9795                in);
9796        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
9797        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
9798        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
9799        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9800        mWifiOn = false;
9801        mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase, in);
9802        mGlobalWifiRunning = false;
9803        mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase, in);
9804        for (int i=0; i<NUM_WIFI_STATES; i++) {
9805            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
9806                    null, mOnBatteryTimeBase, in);
9807        }
9808        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9809            mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i,
9810                    null, mOnBatteryTimeBase, in);
9811        }
9812        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9813            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
9814                    null, mOnBatteryTimeBase, in);
9815        }
9816        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9817            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9818        }
9819        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9820            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9821        }
9822
9823        mHasWifiEnergyReporting = in.readInt() != 0;
9824        mHasBluetoothEnergyReporting = in.readInt() != 0;
9825        mNumConnectivityChange = in.readInt();
9826        mLoadedNumConnectivityChange = in.readInt();
9827        mUnpluggedNumConnectivityChange = in.readInt();
9828        mAudioOnNesting = 0;
9829        mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
9830        mVideoOnNesting = 0;
9831        mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
9832        mFlashlightOnNesting = 0;
9833        mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
9834        mCameraOnNesting = 0;
9835        mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase, in);
9836        mDischargeUnplugLevel = in.readInt();
9837        mDischargePlugLevel = in.readInt();
9838        mDischargeCurrentLevel = in.readInt();
9839        mCurrentBatteryLevel = in.readInt();
9840        mLowDischargeAmountSinceCharge = in.readInt();
9841        mHighDischargeAmountSinceCharge = in.readInt();
9842        mDischargeAmountScreenOn = in.readInt();
9843        mDischargeAmountScreenOnSinceCharge = in.readInt();
9844        mDischargeAmountScreenOff = in.readInt();
9845        mDischargeAmountScreenOffSinceCharge = in.readInt();
9846        mDischargeStepTracker.readFromParcel(in);
9847        mChargeStepTracker.readFromParcel(in);
9848        mLastWriteTime = in.readLong();
9849
9850        mKernelWakelockStats.clear();
9851        int NKW = in.readInt();
9852        for (int ikw = 0; ikw < NKW; ikw++) {
9853            if (in.readInt() != 0) {
9854                String wakelockName = in.readString();
9855                SamplingTimer kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, in);
9856                mKernelWakelockStats.put(wakelockName, kwlt);
9857            }
9858        }
9859
9860        mWakeupReasonStats.clear();
9861        int NWR = in.readInt();
9862        for (int iwr = 0; iwr < NWR; iwr++) {
9863            if (in.readInt() != 0) {
9864                String reasonName = in.readString();
9865                SamplingTimer timer = new SamplingTimer(mOnBatteryTimeBase, in);
9866                mWakeupReasonStats.put(reasonName, timer);
9867            }
9868        }
9869
9870        mPartialTimers.clear();
9871        mFullTimers.clear();
9872        mWindowTimers.clear();
9873        mWifiRunningTimers.clear();
9874        mFullWifiLockTimers.clear();
9875        mWifiScanTimers.clear();
9876        mWifiBatchedScanTimers.clear();
9877        mWifiMulticastTimers.clear();
9878        mAudioTurnedOnTimers.clear();
9879        mVideoTurnedOnTimers.clear();
9880        mFlashlightTurnedOnTimers.clear();
9881        mCameraTurnedOnTimers.clear();
9882
9883        sNumSpeedSteps = in.readInt();
9884
9885        int numUids = in.readInt();
9886        mUidStats.clear();
9887        for (int i = 0; i < numUids; i++) {
9888            int uid = in.readInt();
9889            Uid u = new Uid(uid);
9890            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
9891            mUidStats.append(uid, u);
9892        }
9893    }
9894
9895    public void writeToParcel(Parcel out, int flags) {
9896        writeToParcelLocked(out, true, flags);
9897    }
9898
9899    public void writeToParcelWithoutUids(Parcel out, int flags) {
9900        writeToParcelLocked(out, false, flags);
9901    }
9902
9903    @SuppressWarnings("unused")
9904    void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
9905        // Need to update with current kernel wake lock counts.
9906        pullPendingStateUpdatesLocked();
9907
9908        // Pull the clock time.  This may update the time and make a new history entry
9909        // if we had originally pulled a time before the RTC was set.
9910        long startClockTime = getStartClockTime();
9911
9912        final long uSecUptime = SystemClock.uptimeMillis() * 1000;
9913        final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
9914        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
9915        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
9916
9917        out.writeInt(MAGIC);
9918
9919        writeHistory(out, true, false);
9920
9921        out.writeInt(mStartCount);
9922        out.writeLong(startClockTime);
9923        out.writeString(mStartPlatformVersion);
9924        out.writeString(mEndPlatformVersion);
9925        out.writeLong(mUptime);
9926        out.writeLong(mUptimeStart);
9927        out.writeLong(mRealtime);
9928        out.writeLong(mRealtimeStart);
9929        out.writeInt(mOnBattery ? 1 : 0);
9930        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
9931        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
9932
9933        mScreenOnTimer.writeToParcel(out, uSecRealtime);
9934        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9935            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
9936        }
9937        mInteractiveTimer.writeToParcel(out, uSecRealtime);
9938        mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
9939        mDeviceIdleModeEnabledTimer.writeToParcel(out, uSecRealtime);
9940        mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
9941        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
9942        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9943            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
9944        }
9945        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
9946        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9947            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
9948        }
9949        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9950            mNetworkByteActivityCounters[i].writeToParcel(out);
9951            mNetworkPacketActivityCounters[i].writeToParcel(out);
9952        }
9953        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
9954        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
9955        mMobileRadioActiveAdjustedTime.writeToParcel(out);
9956        mMobileRadioActiveUnknownTime.writeToParcel(out);
9957        mMobileRadioActiveUnknownCount.writeToParcel(out);
9958        mWifiOnTimer.writeToParcel(out, uSecRealtime);
9959        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
9960        for (int i=0; i<NUM_WIFI_STATES; i++) {
9961            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
9962        }
9963        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9964            mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
9965        }
9966        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9967            mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
9968        }
9969        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9970            mBluetoothActivityCounters[i].writeToParcel(out);
9971        }
9972        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9973            mWifiActivityCounters[i].writeToParcel(out);
9974        }
9975        out.writeInt(mHasWifiEnergyReporting ? 1 : 0);
9976        out.writeInt(mHasBluetoothEnergyReporting ? 1 : 0);
9977        out.writeInt(mNumConnectivityChange);
9978        out.writeInt(mLoadedNumConnectivityChange);
9979        out.writeInt(mUnpluggedNumConnectivityChange);
9980        mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
9981        mCameraOnTimer.writeToParcel(out, uSecRealtime);
9982        out.writeInt(mDischargeUnplugLevel);
9983        out.writeInt(mDischargePlugLevel);
9984        out.writeInt(mDischargeCurrentLevel);
9985        out.writeInt(mCurrentBatteryLevel);
9986        out.writeInt(mLowDischargeAmountSinceCharge);
9987        out.writeInt(mHighDischargeAmountSinceCharge);
9988        out.writeInt(mDischargeAmountScreenOn);
9989        out.writeInt(mDischargeAmountScreenOnSinceCharge);
9990        out.writeInt(mDischargeAmountScreenOff);
9991        out.writeInt(mDischargeAmountScreenOffSinceCharge);
9992        mDischargeStepTracker.writeToParcel(out);
9993        mChargeStepTracker.writeToParcel(out);
9994        out.writeLong(mLastWriteTime);
9995
9996        if (inclUids) {
9997            out.writeInt(mKernelWakelockStats.size());
9998            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
9999                SamplingTimer kwlt = ent.getValue();
10000                if (kwlt != null) {
10001                    out.writeInt(1);
10002                    out.writeString(ent.getKey());
10003                    kwlt.writeToParcel(out, uSecRealtime);
10004                } else {
10005                    out.writeInt(0);
10006                }
10007            }
10008            out.writeInt(mWakeupReasonStats.size());
10009            for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
10010                SamplingTimer timer = ent.getValue();
10011                if (timer != null) {
10012                    out.writeInt(1);
10013                    out.writeString(ent.getKey());
10014                    timer.writeToParcel(out, uSecRealtime);
10015                } else {
10016                    out.writeInt(0);
10017                }
10018            }
10019        } else {
10020            out.writeInt(0);
10021        }
10022
10023        out.writeInt(sNumSpeedSteps);
10024
10025        if (inclUids) {
10026            int size = mUidStats.size();
10027            out.writeInt(size);
10028            for (int i = 0; i < size; i++) {
10029                out.writeInt(mUidStats.keyAt(i));
10030                Uid uid = mUidStats.valueAt(i);
10031
10032                uid.writeToParcelLocked(out, uSecRealtime);
10033            }
10034        } else {
10035            out.writeInt(0);
10036        }
10037    }
10038
10039    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
10040        new Parcelable.Creator<BatteryStatsImpl>() {
10041        public BatteryStatsImpl createFromParcel(Parcel in) {
10042            return new BatteryStatsImpl(in);
10043        }
10044
10045        public BatteryStatsImpl[] newArray(int size) {
10046            return new BatteryStatsImpl[size];
10047        }
10048    };
10049
10050    public void prepareForDumpLocked() {
10051        // Need to retrieve current kernel wake lock stats before printing.
10052        pullPendingStateUpdatesLocked();
10053
10054        // Pull the clock time.  This may update the time and make a new history entry
10055        // if we had originally pulled a time before the RTC was set.
10056        getStartClockTime();
10057    }
10058
10059    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
10060        if (DEBUG) {
10061            pw.println("mOnBatteryTimeBase:");
10062            mOnBatteryTimeBase.dump(pw, "  ");
10063            pw.println("mOnBatteryScreenOffTimeBase:");
10064            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
10065            Printer pr = new PrintWriterPrinter(pw);
10066            pr.println("*** Screen timer:");
10067            mScreenOnTimer.logState(pr, "  ");
10068            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10069                pr.println("*** Screen brightness #" + i + ":");
10070                mScreenBrightnessTimer[i].logState(pr, "  ");
10071            }
10072            pr.println("*** Interactive timer:");
10073            mInteractiveTimer.logState(pr, "  ");
10074            pr.println("*** Power save mode timer:");
10075            mPowerSaveModeEnabledTimer.logState(pr, "  ");
10076            pr.println("*** Device idle mode timer:");
10077            mDeviceIdleModeEnabledTimer.logState(pr, "  ");
10078            pr.println("*** Device idling timer:");
10079            mDeviceIdlingTimer.logState(pr, "  ");
10080            pr.println("*** Phone timer:");
10081            mPhoneOnTimer.logState(pr, "  ");
10082            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10083                pr.println("*** Phone signal strength #" + i + ":");
10084                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
10085            }
10086            pr.println("*** Signal scanning :");
10087            mPhoneSignalScanningTimer.logState(pr, "  ");
10088            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10089                pr.println("*** Data connection type #" + i + ":");
10090                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
10091            }
10092            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
10093            pr.println("*** Mobile network active timer:");
10094            mMobileRadioActiveTimer.logState(pr, "  ");
10095            pr.println("*** Mobile network active adjusted timer:");
10096            mMobileRadioActiveAdjustedTime.logState(pr, "  ");
10097            pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
10098            pr.println("*** Wifi timer:");
10099            mWifiOnTimer.logState(pr, "  ");
10100            pr.println("*** WifiRunning timer:");
10101            mGlobalWifiRunningTimer.logState(pr, "  ");
10102            for (int i=0; i<NUM_WIFI_STATES; i++) {
10103                pr.println("*** Wifi state #" + i + ":");
10104                mWifiStateTimer[i].logState(pr, "  ");
10105            }
10106            for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10107                pr.println("*** Wifi suppl state #" + i + ":");
10108                mWifiSupplStateTimer[i].logState(pr, "  ");
10109            }
10110            for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10111                pr.println("*** Wifi signal strength #" + i + ":");
10112                mWifiSignalStrengthsTimer[i].logState(pr, "  ");
10113            }
10114            pr.println("*** Flashlight timer:");
10115            mFlashlightOnTimer.logState(pr, "  ");
10116            pr.println("*** Camera timer:");
10117            mCameraOnTimer.logState(pr, "  ");
10118        }
10119        super.dumpLocked(context, pw, flags, reqUid, histStart);
10120    }
10121}
10122