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