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