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