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