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