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