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