BatteryStatsImpl.java revision 3f8e29715c00d86b4fba136430fe64871c1c6ab6
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        final long elapse = (mClocks.elapsedRealtime() - startTimeMs);
9816        if (DEBUG_ENERGY_CPU || (elapse >= 100)) {
9817            Slog.d(TAG, "Reading cpu stats took " + elapse + " ms");
9818        }
9819
9820        if (mOnBatteryInternal && numWakelocks > 0) {
9821            // Distribute a portion of the total cpu time to wakelock holders.
9822            mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
9823            mTempTotalCpuSystemTimeUs =
9824                    (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
9825
9826            for (int i = 0; i < numPartialTimers; i++) {
9827                final StopwatchTimer timer = mPartialTimers.get(i);
9828
9829                // The system does not share any blame, as it is usually holding the wakelock
9830                // on behalf of an app.
9831                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
9832                    int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
9833                    int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
9834
9835                    if (DEBUG_ENERGY_CPU) {
9836                        StringBuilder sb = new StringBuilder();
9837                        sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
9838                                .append(": u=");
9839                        TimeUtils.formatDuration(userTimeUs / 1000, sb);
9840                        sb.append(" s=");
9841                        TimeUtils.formatDuration(systemTimeUs / 1000, sb);
9842                        Slog.d(TAG, sb.toString());
9843                    }
9844
9845                    timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
9846                    timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
9847
9848                    final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
9849                    proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
9850
9851                    mTempTotalCpuUserTimeUs -= userTimeUs;
9852                    mTempTotalCpuSystemTimeUs -= systemTimeUs;
9853                    numWakelocks--;
9854                }
9855            }
9856
9857            if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
9858                // Anything left over is given to the system.
9859                if (DEBUG_ENERGY_CPU) {
9860                    StringBuilder sb = new StringBuilder();
9861                    sb.append("  Distributing lost time to system: u=");
9862                    TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
9863                    sb.append(" s=");
9864                    TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
9865                    Slog.d(TAG, sb.toString());
9866                }
9867
9868                final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
9869                u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
9870                u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
9871
9872                final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
9873                proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000,
9874                        (int) mTempTotalCpuSystemTimeUs / 1000);
9875            }
9876        }
9877
9878        // See if there is a difference in wakelocks between this collection and the last
9879        // collection.
9880        if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
9881            // No difference, so each timer is now considered for the next collection.
9882            for (int i = 0; i < numPartialTimers; i++) {
9883                mPartialTimers.get(i).mInList = true;
9884            }
9885        } else {
9886            // The lists are different, meaning we added (or removed a timer) since the last
9887            // collection.
9888            final int numLastPartialTimers = mLastPartialTimers.size();
9889            for (int i = 0; i < numLastPartialTimers; i++) {
9890                mLastPartialTimers.get(i).mInList = false;
9891            }
9892            mLastPartialTimers.clear();
9893
9894            // Mark the current timers as gone through a collection.
9895            for (int i = 0; i < numPartialTimers; i++) {
9896                final StopwatchTimer timer = mPartialTimers.get(i);
9897                timer.mInList = true;
9898                mLastPartialTimers.add(timer);
9899            }
9900        }
9901    }
9902
9903    boolean setChargingLocked(boolean charging) {
9904        if (mCharging != charging) {
9905            mCharging = charging;
9906            if (charging) {
9907                mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
9908            } else {
9909                mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
9910            }
9911            mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
9912            return true;
9913        }
9914        return false;
9915    }
9916
9917    void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
9918            final int oldStatus, final int level, final int chargeUAh) {
9919        boolean doWrite = false;
9920        Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
9921        m.arg1 = onBattery ? 1 : 0;
9922        mHandler.sendMessage(m);
9923
9924        final long uptime = mSecUptime * 1000;
9925        final long realtime = mSecRealtime * 1000;
9926        final boolean screenOn = mScreenState == Display.STATE_ON;
9927        if (onBattery) {
9928            // We will reset our status if we are unplugging after the
9929            // battery was last full, or the level is at 100, or
9930            // we have gone through a significant charge (from a very low
9931            // level to a now very high level).
9932            boolean reset = false;
9933            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
9934                    || level >= 90
9935                    || (mDischargeCurrentLevel < 20 && level >= 80)
9936                    || (getHighDischargeAmountSinceCharge() >= 200
9937                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
9938                Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
9939                        + " dischargeLevel=" + mDischargeCurrentLevel
9940                        + " lowAmount=" + getLowDischargeAmountSinceCharge()
9941                        + " highAmount=" + getHighDischargeAmountSinceCharge());
9942                // Before we write, collect a snapshot of the final aggregated
9943                // stats to be reported in the next checkin.  Only do this if we have
9944                // a sufficient amount of data to make it interesting.
9945                if (getLowDischargeAmountSinceCharge() >= 20) {
9946                    final Parcel parcel = Parcel.obtain();
9947                    writeSummaryToParcel(parcel, true);
9948                    BackgroundThread.getHandler().post(new Runnable() {
9949                        @Override public void run() {
9950                            synchronized (mCheckinFile) {
9951                                FileOutputStream stream = null;
9952                                try {
9953                                    stream = mCheckinFile.startWrite();
9954                                    stream.write(parcel.marshall());
9955                                    stream.flush();
9956                                    FileUtils.sync(stream);
9957                                    stream.close();
9958                                    mCheckinFile.finishWrite(stream);
9959                                } catch (IOException e) {
9960                                    Slog.w("BatteryStats",
9961                                            "Error writing checkin battery statistics", e);
9962                                    mCheckinFile.failWrite(stream);
9963                                } finally {
9964                                    parcel.recycle();
9965                                }
9966                            }
9967                        }
9968                    });
9969                }
9970                doWrite = true;
9971                resetAllStatsLocked();
9972                if (chargeUAh > 0 && level > 0) {
9973                    // Only use the reported coulomb charge value if it is supported and reported.
9974                    mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
9975                }
9976                mDischargeStartLevel = level;
9977                reset = true;
9978                mDischargeStepTracker.init();
9979            }
9980            if (mCharging) {
9981                setChargingLocked(false);
9982            }
9983            mLastChargingStateLevel = level;
9984            mOnBattery = mOnBatteryInternal = true;
9985            mLastDischargeStepLevel = level;
9986            mMinDischargeStepLevel = level;
9987            mDischargeStepTracker.clearTime();
9988            mDailyDischargeStepTracker.clearTime();
9989            mInitStepMode = mCurStepMode;
9990            mModStepMode = 0;
9991            pullPendingStateUpdatesLocked();
9992            mHistoryCur.batteryLevel = (byte)level;
9993            mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
9994            if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
9995                    + Integer.toHexString(mHistoryCur.states));
9996            if (reset) {
9997                mRecordingHistory = true;
9998                startRecordingHistory(mSecRealtime, mSecUptime, reset);
9999            }
10000            addHistoryRecordLocked(mSecRealtime, mSecUptime);
10001            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
10002            if (screenOn) {
10003                mDischargeScreenOnUnplugLevel = level;
10004                mDischargeScreenOffUnplugLevel = 0;
10005            } else {
10006                mDischargeScreenOnUnplugLevel = 0;
10007                mDischargeScreenOffUnplugLevel = level;
10008            }
10009            mDischargeAmountScreenOn = 0;
10010            mDischargeAmountScreenOff = 0;
10011            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
10012        } else {
10013            mLastChargingStateLevel = level;
10014            mOnBattery = mOnBatteryInternal = false;
10015            pullPendingStateUpdatesLocked();
10016            mHistoryCur.batteryLevel = (byte)level;
10017            mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
10018            if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
10019                    + Integer.toHexString(mHistoryCur.states));
10020            addHistoryRecordLocked(mSecRealtime, mSecUptime);
10021            mDischargeCurrentLevel = mDischargePlugLevel = level;
10022            if (level < mDischargeUnplugLevel) {
10023                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
10024                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
10025            }
10026            updateDischargeScreenLevelsLocked(screenOn, screenOn);
10027            updateTimeBasesLocked(false, !screenOn, uptime, realtime);
10028            mChargeStepTracker.init();
10029            mLastChargeStepLevel = level;
10030            mMaxChargeStepLevel = level;
10031            mInitStepMode = mCurStepMode;
10032            mModStepMode = 0;
10033        }
10034        if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
10035            if (mFile != null) {
10036                writeAsyncLocked();
10037            }
10038        }
10039    }
10040
10041    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
10042            boolean reset) {
10043        mRecordingHistory = true;
10044        mHistoryCur.currentTime = System.currentTimeMillis();
10045        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
10046                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
10047                mHistoryCur);
10048        mHistoryCur.currentTime = 0;
10049        if (reset) {
10050            initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
10051        }
10052    }
10053
10054    private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
10055            final long uptimeMs) {
10056        if (mRecordingHistory) {
10057            mHistoryCur.currentTime = currentTime;
10058            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
10059                    mHistoryCur);
10060            mHistoryCur.currentTime = 0;
10061        }
10062    }
10063
10064    private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
10065        if (mRecordingHistory) {
10066            mHistoryCur.currentTime = System.currentTimeMillis();
10067            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
10068                    mHistoryCur);
10069            mHistoryCur.currentTime = 0;
10070        }
10071    }
10072
10073    private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
10074        if (mExternalSync != null) {
10075            mExternalSync.scheduleSync(reason, updateFlags);
10076        }
10077    }
10078
10079    // This should probably be exposed in the API, though it's not critical
10080    public static final int BATTERY_PLUGGED_NONE = 0;
10081
10082    public void setBatteryStateLocked(int status, int health, int plugType, int level,
10083            int temp, int volt, int chargeUAh, int chargeFullUAh) {
10084        // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
10085        temp = Math.max(0, temp);
10086
10087        final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
10088        final long uptime = mClocks.uptimeMillis();
10089        final long elapsedRealtime = mClocks.elapsedRealtime();
10090        if (!mHaveBatteryLevel) {
10091            mHaveBatteryLevel = true;
10092            // We start out assuming that the device is plugged in (not
10093            // on battery).  If our first report is now that we are indeed
10094            // plugged in, then twiddle our state to correctly reflect that
10095            // since we won't be going through the full setOnBattery().
10096            if (onBattery == mOnBattery) {
10097                if (onBattery) {
10098                    mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
10099                } else {
10100                    mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
10101                }
10102            }
10103            // Always start out assuming charging, that will be updated later.
10104            mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
10105            mHistoryCur.batteryStatus = (byte)status;
10106            mHistoryCur.batteryLevel = (byte)level;
10107            mHistoryCur.batteryChargeUAh = chargeUAh;
10108            mMaxChargeStepLevel = mMinDischargeStepLevel =
10109                    mLastChargeStepLevel = mLastDischargeStepLevel = level;
10110            mLastChargingStateLevel = level;
10111        } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
10112            recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
10113        }
10114        int oldStatus = mHistoryCur.batteryStatus;
10115        if (onBattery) {
10116            mDischargeCurrentLevel = level;
10117            if (!mRecordingHistory) {
10118                mRecordingHistory = true;
10119                startRecordingHistory(elapsedRealtime, uptime, true);
10120            }
10121        } else if (level < 96) {
10122            if (!mRecordingHistory) {
10123                mRecordingHistory = true;
10124                startRecordingHistory(elapsedRealtime, uptime, true);
10125            }
10126        }
10127        mCurrentBatteryLevel = level;
10128        if (mDischargePlugLevel < 0) {
10129            mDischargePlugLevel = level;
10130        }
10131
10132        if (onBattery != mOnBattery) {
10133            mHistoryCur.batteryLevel = (byte)level;
10134            mHistoryCur.batteryStatus = (byte)status;
10135            mHistoryCur.batteryHealth = (byte)health;
10136            mHistoryCur.batteryPlugType = (byte)plugType;
10137            mHistoryCur.batteryTemperature = (short)temp;
10138            mHistoryCur.batteryVoltage = (char)volt;
10139            if (chargeUAh < mHistoryCur.batteryChargeUAh) {
10140                // Only record discharges
10141                final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
10142                mDischargeCounter.addCountLocked(chargeDiff);
10143                mDischargeScreenOffCounter.addCountLocked(chargeDiff);
10144            }
10145            mHistoryCur.batteryChargeUAh = chargeUAh;
10146            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
10147        } else {
10148            boolean changed = false;
10149            if (mHistoryCur.batteryLevel != level) {
10150                mHistoryCur.batteryLevel = (byte)level;
10151                changed = true;
10152
10153                // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
10154                // which will pull external stats.
10155                scheduleSyncExternalStatsLocked("battery-level", ExternalStatsSync.UPDATE_ALL);
10156            }
10157            if (mHistoryCur.batteryStatus != status) {
10158                mHistoryCur.batteryStatus = (byte)status;
10159                changed = true;
10160            }
10161            if (mHistoryCur.batteryHealth != health) {
10162                mHistoryCur.batteryHealth = (byte)health;
10163                changed = true;
10164            }
10165            if (mHistoryCur.batteryPlugType != plugType) {
10166                mHistoryCur.batteryPlugType = (byte)plugType;
10167                changed = true;
10168            }
10169            if (temp >= (mHistoryCur.batteryTemperature+10)
10170                    || temp <= (mHistoryCur.batteryTemperature-10)) {
10171                mHistoryCur.batteryTemperature = (short)temp;
10172                changed = true;
10173            }
10174            if (volt > (mHistoryCur.batteryVoltage+20)
10175                    || volt < (mHistoryCur.batteryVoltage-20)) {
10176                mHistoryCur.batteryVoltage = (char)volt;
10177                changed = true;
10178            }
10179            if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
10180                    || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
10181                if (chargeUAh < mHistoryCur.batteryChargeUAh) {
10182                    // Only record discharges
10183                    final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
10184                    mDischargeCounter.addCountLocked(chargeDiff);
10185                    mDischargeScreenOffCounter.addCountLocked(chargeDiff);
10186                }
10187                mHistoryCur.batteryChargeUAh = chargeUAh;
10188                changed = true;
10189            }
10190            long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
10191                    | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
10192                    | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
10193            if (onBattery) {
10194                changed |= setChargingLocked(false);
10195                if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
10196                    mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
10197                            modeBits, elapsedRealtime);
10198                    mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
10199                            modeBits, elapsedRealtime);
10200                    mLastDischargeStepLevel = level;
10201                    mMinDischargeStepLevel = level;
10202                    mInitStepMode = mCurStepMode;
10203                    mModStepMode = 0;
10204                }
10205            } else {
10206                if (level >= 90) {
10207                    // If the battery level is at least 90%, always consider the device to be
10208                    // charging even if it happens to go down a level.
10209                    changed |= setChargingLocked(true);
10210                    mLastChargeStepLevel = level;
10211                } if (!mCharging) {
10212                    if (mLastChargeStepLevel < level) {
10213                        // We have not reporting that we are charging, but the level has now
10214                        // gone up, so consider the state to be charging.
10215                        changed |= setChargingLocked(true);
10216                        mLastChargeStepLevel = level;
10217                    }
10218                } else {
10219                    if (mLastChargeStepLevel > level) {
10220                        // We had reported that the device was charging, but here we are with
10221                        // power connected and the level going down.  Looks like the current
10222                        // power supplied isn't enough, so consider the device to now be
10223                        // discharging.
10224                        changed |= setChargingLocked(false);
10225                        mLastChargeStepLevel = level;
10226                    }
10227                }
10228                if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
10229                    mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
10230                            modeBits, elapsedRealtime);
10231                    mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
10232                            modeBits, elapsedRealtime);
10233                    mLastChargeStepLevel = level;
10234                    mMaxChargeStepLevel = level;
10235                    mInitStepMode = mCurStepMode;
10236                    mModStepMode = 0;
10237                }
10238            }
10239            if (changed) {
10240                addHistoryRecordLocked(elapsedRealtime, uptime);
10241            }
10242        }
10243        if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
10244            // We don't record history while we are plugged in and fully charged.
10245            // The next time we are unplugged, history will be cleared.
10246            mRecordingHistory = DEBUG;
10247        }
10248
10249        if (mMinLearnedBatteryCapacity == -1) {
10250            mMinLearnedBatteryCapacity = chargeFullUAh;
10251        } else {
10252            Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
10253        }
10254        mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
10255    }
10256
10257    public long getAwakeTimeBattery() {
10258        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
10259    }
10260
10261    public long getAwakeTimePlugged() {
10262        return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
10263    }
10264
10265    @Override
10266    public long computeUptime(long curTime, int which) {
10267        switch (which) {
10268            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
10269            case STATS_CURRENT: return (curTime-mUptimeStart);
10270            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
10271        }
10272        return 0;
10273    }
10274
10275    @Override
10276    public long computeRealtime(long curTime, int which) {
10277        switch (which) {
10278            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
10279            case STATS_CURRENT: return (curTime-mRealtimeStart);
10280            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
10281        }
10282        return 0;
10283    }
10284
10285    @Override
10286    public long computeBatteryUptime(long curTime, int which) {
10287        return mOnBatteryTimeBase.computeUptime(curTime, which);
10288    }
10289
10290    @Override
10291    public long computeBatteryRealtime(long curTime, int which) {
10292        return mOnBatteryTimeBase.computeRealtime(curTime, which);
10293    }
10294
10295    @Override
10296    public long computeBatteryScreenOffUptime(long curTime, int which) {
10297        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
10298    }
10299
10300    @Override
10301    public long computeBatteryScreenOffRealtime(long curTime, int which) {
10302        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
10303    }
10304
10305    private long computeTimePerLevel(long[] steps, int numSteps) {
10306        // For now we'll do a simple average across all steps.
10307        if (numSteps <= 0) {
10308            return -1;
10309        }
10310        long total = 0;
10311        for (int i=0; i<numSteps; i++) {
10312            total += steps[i] & STEP_LEVEL_TIME_MASK;
10313        }
10314        return total / numSteps;
10315        /*
10316        long[] buckets = new long[numSteps];
10317        int numBuckets = 0;
10318        int numToAverage = 4;
10319        int i = 0;
10320        while (i < numSteps) {
10321            long totalTime = 0;
10322            int num = 0;
10323            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
10324                totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
10325                num++;
10326            }
10327            buckets[numBuckets] = totalTime / num;
10328            numBuckets++;
10329            numToAverage *= 2;
10330            i += num;
10331        }
10332        if (numBuckets < 1) {
10333            return -1;
10334        }
10335        long averageTime = buckets[numBuckets-1];
10336        for (i=numBuckets-2; i>=0; i--) {
10337            averageTime = (averageTime + buckets[i]) / 2;
10338        }
10339        return averageTime;
10340        */
10341    }
10342
10343    @Override
10344    public long computeBatteryTimeRemaining(long curTime) {
10345        if (!mOnBattery) {
10346            return -1;
10347        }
10348        /* Simple implementation just looks at the average discharge per level across the
10349           entire sample period.
10350        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
10351        if (discharge < 2) {
10352            return -1;
10353        }
10354        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
10355        if (duration < 1000*1000) {
10356            return -1;
10357        }
10358        long usPerLevel = duration/discharge;
10359        return usPerLevel * mCurrentBatteryLevel;
10360        */
10361        if (mDischargeStepTracker.mNumStepDurations < 1) {
10362            return -1;
10363        }
10364        long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
10365        if (msPerLevel <= 0) {
10366            return -1;
10367        }
10368        return (msPerLevel * mCurrentBatteryLevel) * 1000;
10369    }
10370
10371    @Override
10372    public LevelStepTracker getDischargeLevelStepTracker() {
10373        return mDischargeStepTracker;
10374    }
10375
10376    @Override
10377    public LevelStepTracker getDailyDischargeLevelStepTracker() {
10378        return mDailyDischargeStepTracker;
10379    }
10380
10381    @Override
10382    public long computeChargeTimeRemaining(long curTime) {
10383        if (mOnBattery) {
10384            // Not yet working.
10385            return -1;
10386        }
10387        /* Broken
10388        int curLevel = mCurrentBatteryLevel;
10389        int plugLevel = mDischargePlugLevel;
10390        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
10391            return -1;
10392        }
10393        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
10394        if (duration < 1000*1000) {
10395            return -1;
10396        }
10397        long usPerLevel = duration/(curLevel-plugLevel);
10398        return usPerLevel * (100-curLevel);
10399        */
10400        if (mChargeStepTracker.mNumStepDurations < 1) {
10401            return -1;
10402        }
10403        long msPerLevel = mChargeStepTracker.computeTimePerLevel();
10404        if (msPerLevel <= 0) {
10405            return -1;
10406        }
10407        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
10408    }
10409
10410    @Override
10411    public LevelStepTracker getChargeLevelStepTracker() {
10412        return mChargeStepTracker;
10413    }
10414
10415    @Override
10416    public LevelStepTracker getDailyChargeLevelStepTracker() {
10417        return mDailyChargeStepTracker;
10418    }
10419
10420    @Override
10421    public ArrayList<PackageChange> getDailyPackageChanges() {
10422        return mDailyPackageChanges;
10423    }
10424
10425    protected long getBatteryUptimeLocked() {
10426        return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
10427    }
10428
10429    @Override
10430    public long getBatteryUptime(long curTime) {
10431        return mOnBatteryTimeBase.getUptime(curTime);
10432    }
10433
10434    @Override
10435    public long getBatteryRealtime(long curTime) {
10436        return mOnBatteryTimeBase.getRealtime(curTime);
10437    }
10438
10439    @Override
10440    public int getDischargeStartLevel() {
10441        synchronized(this) {
10442            return getDischargeStartLevelLocked();
10443        }
10444    }
10445
10446    public int getDischargeStartLevelLocked() {
10447            return mDischargeUnplugLevel;
10448    }
10449
10450    @Override
10451    public int getDischargeCurrentLevel() {
10452        synchronized(this) {
10453            return getDischargeCurrentLevelLocked();
10454        }
10455    }
10456
10457    public int getDischargeCurrentLevelLocked() {
10458        return mDischargeCurrentLevel;
10459    }
10460
10461    @Override
10462    public int getLowDischargeAmountSinceCharge() {
10463        synchronized(this) {
10464            int val = mLowDischargeAmountSinceCharge;
10465            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
10466                val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
10467            }
10468            return val;
10469        }
10470    }
10471
10472    @Override
10473    public int getHighDischargeAmountSinceCharge() {
10474        synchronized(this) {
10475            int val = mHighDischargeAmountSinceCharge;
10476            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
10477                val += mDischargeUnplugLevel-mDischargeCurrentLevel;
10478            }
10479            return val;
10480        }
10481    }
10482
10483    @Override
10484    public int getDischargeAmount(int which) {
10485        int dischargeAmount = which == STATS_SINCE_CHARGED
10486                ? getHighDischargeAmountSinceCharge()
10487                : (getDischargeStartLevel() - getDischargeCurrentLevel());
10488        if (dischargeAmount < 0) {
10489            dischargeAmount = 0;
10490        }
10491        return dischargeAmount;
10492    }
10493
10494    public int getDischargeAmountScreenOn() {
10495        synchronized(this) {
10496            int val = mDischargeAmountScreenOn;
10497            if (mOnBattery && mScreenState == Display.STATE_ON
10498                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
10499                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
10500            }
10501            return val;
10502        }
10503    }
10504
10505    public int getDischargeAmountScreenOnSinceCharge() {
10506        synchronized(this) {
10507            int val = mDischargeAmountScreenOnSinceCharge;
10508            if (mOnBattery && mScreenState == Display.STATE_ON
10509                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
10510                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
10511            }
10512            return val;
10513        }
10514    }
10515
10516    public int getDischargeAmountScreenOff() {
10517        synchronized(this) {
10518            int val = mDischargeAmountScreenOff;
10519            if (mOnBattery && mScreenState != Display.STATE_ON
10520                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
10521                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
10522            }
10523            return val;
10524        }
10525    }
10526
10527    public int getDischargeAmountScreenOffSinceCharge() {
10528        synchronized(this) {
10529            int val = mDischargeAmountScreenOffSinceCharge;
10530            if (mOnBattery && mScreenState != Display.STATE_ON
10531                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
10532                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
10533            }
10534            return val;
10535        }
10536    }
10537
10538    /**
10539     * Retrieve the statistics object for a particular uid, creating if needed.
10540     */
10541    public Uid getUidStatsLocked(int uid) {
10542        Uid u = mUidStats.get(uid);
10543        if (u == null) {
10544            u = new Uid(this, uid);
10545            mUidStats.put(uid, u);
10546        }
10547        return u;
10548    }
10549
10550    /**
10551     * Remove the statistics object for a particular uid.
10552     */
10553    public void removeUidStatsLocked(int uid) {
10554        mKernelUidCpuTimeReader.removeUid(uid);
10555        mUidStats.remove(uid);
10556    }
10557
10558    /**
10559     * Retrieve the statistics object for a particular process, creating
10560     * if needed.
10561     */
10562    public Uid.Proc getProcessStatsLocked(int uid, String name) {
10563        uid = mapUid(uid);
10564        Uid u = getUidStatsLocked(uid);
10565        return u.getProcessStatsLocked(name);
10566    }
10567
10568    /**
10569     * Retrieve the statistics object for a particular process, creating
10570     * if needed.
10571     */
10572    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
10573        uid = mapUid(uid);
10574        Uid u = getUidStatsLocked(uid);
10575        return u.getPackageStatsLocked(pkg);
10576    }
10577
10578    /**
10579     * Retrieve the statistics object for a particular service, creating
10580     * if needed.
10581     */
10582    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
10583        uid = mapUid(uid);
10584        Uid u = getUidStatsLocked(uid);
10585        return u.getServiceStatsLocked(pkg, name);
10586    }
10587
10588    public void shutdownLocked() {
10589        recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
10590        writeSyncLocked();
10591        mShuttingDown = true;
10592    }
10593
10594    Parcel mPendingWrite = null;
10595    final ReentrantLock mWriteLock = new ReentrantLock();
10596
10597    public void writeAsyncLocked() {
10598        writeLocked(false);
10599    }
10600
10601    public void writeSyncLocked() {
10602        writeLocked(true);
10603    }
10604
10605    void writeLocked(boolean sync) {
10606        if (mFile == null) {
10607            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
10608            return;
10609        }
10610
10611        if (mShuttingDown) {
10612            return;
10613        }
10614
10615        Parcel out = Parcel.obtain();
10616        writeSummaryToParcel(out, true);
10617        mLastWriteTime = mClocks.elapsedRealtime();
10618
10619        if (mPendingWrite != null) {
10620            mPendingWrite.recycle();
10621        }
10622        mPendingWrite = out;
10623
10624        if (sync) {
10625            commitPendingDataToDisk();
10626        } else {
10627            BackgroundThread.getHandler().post(new Runnable() {
10628                @Override public void run() {
10629                    commitPendingDataToDisk();
10630                }
10631            });
10632        }
10633    }
10634
10635    public void commitPendingDataToDisk() {
10636        final Parcel next;
10637        synchronized (this) {
10638            next = mPendingWrite;
10639            mPendingWrite = null;
10640            if (next == null) {
10641                return;
10642            }
10643        }
10644
10645        mWriteLock.lock();
10646        try {
10647            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
10648            stream.write(next.marshall());
10649            stream.flush();
10650            FileUtils.sync(stream);
10651            stream.close();
10652            mFile.commit();
10653        } catch (IOException e) {
10654            Slog.w("BatteryStats", "Error writing battery statistics", e);
10655            mFile.rollback();
10656        } finally {
10657            next.recycle();
10658            mWriteLock.unlock();
10659        }
10660    }
10661
10662    public void readLocked() {
10663        if (mDailyFile != null) {
10664            readDailyStatsLocked();
10665        }
10666
10667        if (mFile == null) {
10668            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
10669            return;
10670        }
10671
10672        mUidStats.clear();
10673
10674        try {
10675            File file = mFile.chooseForRead();
10676            if (!file.exists()) {
10677                return;
10678            }
10679            FileInputStream stream = new FileInputStream(file);
10680
10681            byte[] raw = BatteryStatsHelper.readFully(stream);
10682            Parcel in = Parcel.obtain();
10683            in.unmarshall(raw, 0, raw.length);
10684            in.setDataPosition(0);
10685            stream.close();
10686
10687            readSummaryFromParcel(in);
10688        } catch(Exception e) {
10689            Slog.e("BatteryStats", "Error reading battery statistics", e);
10690            resetAllStatsLocked();
10691        }
10692
10693        mEndPlatformVersion = Build.ID;
10694
10695        if (mHistoryBuffer.dataPosition() > 0) {
10696            mRecordingHistory = true;
10697            final long elapsedRealtime = mClocks.elapsedRealtime();
10698            final long uptime = mClocks.uptimeMillis();
10699            if (USE_OLD_HISTORY) {
10700                addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
10701            }
10702            addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
10703            startRecordingHistory(elapsedRealtime, uptime, false);
10704        }
10705
10706        recordDailyStatsIfNeededLocked(false);
10707    }
10708
10709    public int describeContents() {
10710        return 0;
10711    }
10712
10713    void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
10714        final long historyBaseTime = in.readLong();
10715
10716        mHistoryBuffer.setDataSize(0);
10717        mHistoryBuffer.setDataPosition(0);
10718        mHistoryTagPool.clear();
10719        mNextHistoryTagIdx = 0;
10720        mNumHistoryTagChars = 0;
10721
10722        int numTags = in.readInt();
10723        for (int i=0; i<numTags; i++) {
10724            int idx = in.readInt();
10725            String str = in.readString();
10726            if (str == null) {
10727                throw new ParcelFormatException("null history tag string");
10728            }
10729            int uid = in.readInt();
10730            HistoryTag tag = new HistoryTag();
10731            tag.string = str;
10732            tag.uid = uid;
10733            tag.poolIdx = idx;
10734            mHistoryTagPool.put(tag, idx);
10735            if (idx >= mNextHistoryTagIdx) {
10736                mNextHistoryTagIdx = idx+1;
10737            }
10738            mNumHistoryTagChars += tag.string.length() + 1;
10739        }
10740
10741        int bufSize = in.readInt();
10742        int curPos = in.dataPosition();
10743        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
10744            throw new ParcelFormatException("File corrupt: history data buffer too large " +
10745                    bufSize);
10746        } else if ((bufSize&~3) != bufSize) {
10747            throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
10748                    bufSize);
10749        } else {
10750            if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
10751                    + " bytes at " + curPos);
10752            mHistoryBuffer.appendFrom(in, curPos, bufSize);
10753            in.setDataPosition(curPos + bufSize);
10754        }
10755
10756        if (andOldHistory) {
10757            readOldHistory(in);
10758        }
10759
10760        if (DEBUG_HISTORY) {
10761            StringBuilder sb = new StringBuilder(128);
10762            sb.append("****************** OLD mHistoryBaseTime: ");
10763            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10764            Slog.i(TAG, sb.toString());
10765        }
10766        mHistoryBaseTime = historyBaseTime;
10767        if (DEBUG_HISTORY) {
10768            StringBuilder sb = new StringBuilder(128);
10769            sb.append("****************** NEW mHistoryBaseTime: ");
10770            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10771            Slog.i(TAG, sb.toString());
10772        }
10773
10774        // We are just arbitrarily going to insert 1 minute from the sample of
10775        // the last run until samples in this run.
10776        if (mHistoryBaseTime > 0) {
10777            long oldnow = mClocks.elapsedRealtime();
10778            mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
10779            if (DEBUG_HISTORY) {
10780                StringBuilder sb = new StringBuilder(128);
10781                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
10782                TimeUtils.formatDuration(mHistoryBaseTime, sb);
10783                Slog.i(TAG, sb.toString());
10784            }
10785        }
10786    }
10787
10788    void readOldHistory(Parcel in) {
10789        if (!USE_OLD_HISTORY) {
10790            return;
10791        }
10792        mHistory = mHistoryEnd = mHistoryCache = null;
10793        long time;
10794        while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
10795            HistoryItem rec = new HistoryItem(time, in);
10796            addHistoryRecordLocked(rec);
10797        }
10798    }
10799
10800    void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
10801        if (DEBUG_HISTORY) {
10802            StringBuilder sb = new StringBuilder(128);
10803            sb.append("****************** WRITING mHistoryBaseTime: ");
10804            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10805            sb.append(" mLastHistoryElapsedRealtime: ");
10806            TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
10807            Slog.i(TAG, sb.toString());
10808        }
10809        out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
10810        if (!inclData) {
10811            out.writeInt(0);
10812            out.writeInt(0);
10813            return;
10814        }
10815        out.writeInt(mHistoryTagPool.size());
10816        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10817            HistoryTag tag = ent.getKey();
10818            out.writeInt(ent.getValue());
10819            out.writeString(tag.string);
10820            out.writeInt(tag.uid);
10821        }
10822        out.writeInt(mHistoryBuffer.dataSize());
10823        if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
10824                + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
10825        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
10826
10827        if (andOldHistory) {
10828            writeOldHistory(out);
10829        }
10830    }
10831
10832    void writeOldHistory(Parcel out) {
10833        if (!USE_OLD_HISTORY) {
10834            return;
10835        }
10836        HistoryItem rec = mHistory;
10837        while (rec != null) {
10838            if (rec.time >= 0) rec.writeToParcel(out, 0);
10839            rec = rec.next;
10840        }
10841        out.writeLong(-1);
10842    }
10843
10844    public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
10845        final int version = in.readInt();
10846        if (version != VERSION) {
10847            Slog.w("BatteryStats", "readFromParcel: version got " + version
10848                + ", expected " + VERSION + "; erasing old stats");
10849            return;
10850        }
10851
10852        readHistory(in, true);
10853
10854        mStartCount = in.readInt();
10855        mUptime = in.readLong();
10856        mRealtime = in.readLong();
10857        mStartClockTime = in.readLong();
10858        mStartPlatformVersion = in.readString();
10859        mEndPlatformVersion = in.readString();
10860        mOnBatteryTimeBase.readSummaryFromParcel(in);
10861        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
10862        mDischargeUnplugLevel = in.readInt();
10863        mDischargePlugLevel = in.readInt();
10864        mDischargeCurrentLevel = in.readInt();
10865        mCurrentBatteryLevel = in.readInt();
10866        mEstimatedBatteryCapacity = in.readInt();
10867        mMinLearnedBatteryCapacity = in.readInt();
10868        mMaxLearnedBatteryCapacity = in.readInt();
10869        mLowDischargeAmountSinceCharge = in.readInt();
10870        mHighDischargeAmountSinceCharge = in.readInt();
10871        mDischargeAmountScreenOnSinceCharge = in.readInt();
10872        mDischargeAmountScreenOffSinceCharge = in.readInt();
10873        mDischargeStepTracker.readFromParcel(in);
10874        mChargeStepTracker.readFromParcel(in);
10875        mDailyDischargeStepTracker.readFromParcel(in);
10876        mDailyChargeStepTracker.readFromParcel(in);
10877        mDischargeCounter.readSummaryFromParcelLocked(in);
10878        mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
10879        int NPKG = in.readInt();
10880        if (NPKG > 0) {
10881            mDailyPackageChanges = new ArrayList<>(NPKG);
10882            while (NPKG > 0) {
10883                NPKG--;
10884                PackageChange pc = new PackageChange();
10885                pc.mPackageName = in.readString();
10886                pc.mUpdate = in.readInt() != 0;
10887                pc.mVersionCode = in.readInt();
10888                mDailyPackageChanges.add(pc);
10889            }
10890        } else {
10891            mDailyPackageChanges = null;
10892        }
10893        mDailyStartTime = in.readLong();
10894        mNextMinDailyDeadline = in.readLong();
10895        mNextMaxDailyDeadline = in.readLong();
10896
10897        mStartCount++;
10898
10899        mScreenState = Display.STATE_UNKNOWN;
10900        mScreenOnTimer.readSummaryFromParcelLocked(in);
10901        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10902            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
10903        }
10904        mInteractive = false;
10905        mInteractiveTimer.readSummaryFromParcelLocked(in);
10906        mPhoneOn = false;
10907        mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
10908        mLongestLightIdleTime = in.readLong();
10909        mLongestFullIdleTime = in.readLong();
10910        mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
10911        mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
10912        mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
10913        mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
10914        mPhoneOnTimer.readSummaryFromParcelLocked(in);
10915        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10916            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
10917        }
10918        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
10919        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10920            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
10921        }
10922        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10923            mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
10924            mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
10925        }
10926        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10927        mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
10928        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
10929        mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
10930        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
10931        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
10932        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10933        mWifiOn = false;
10934        mWifiOnTimer.readSummaryFromParcelLocked(in);
10935        mGlobalWifiRunning = false;
10936        mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
10937        for (int i=0; i<NUM_WIFI_STATES; i++) {
10938            mWifiStateTimer[i].readSummaryFromParcelLocked(in);
10939        }
10940        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10941            mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
10942        }
10943        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10944            mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
10945        }
10946        mWifiActivity.readSummaryFromParcel(in);
10947        mBluetoothActivity.readSummaryFromParcel(in);
10948        mModemActivity.readSummaryFromParcel(in);
10949        mHasWifiReporting = in.readInt() != 0;
10950        mHasBluetoothReporting = in.readInt() != 0;
10951        mHasModemReporting = in.readInt() != 0;
10952
10953        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
10954        mFlashlightOnNesting = 0;
10955        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
10956        mCameraOnNesting = 0;
10957        mCameraOnTimer.readSummaryFromParcelLocked(in);
10958        mBluetoothScanNesting = 0;
10959        mBluetoothScanTimer.readSummaryFromParcelLocked(in);
10960
10961        int NKW = in.readInt();
10962        if (NKW > 10000) {
10963            throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
10964        }
10965        for (int ikw = 0; ikw < NKW; ikw++) {
10966            if (in.readInt() != 0) {
10967                String kwltName = in.readString();
10968                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
10969            }
10970        }
10971
10972        int NWR = in.readInt();
10973        if (NWR > 10000) {
10974            throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
10975        }
10976        for (int iwr = 0; iwr < NWR; iwr++) {
10977            if (in.readInt() != 0) {
10978                String reasonName = in.readString();
10979                getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
10980            }
10981        }
10982
10983        int NMS = in.readInt();
10984        for (int ims = 0; ims < NMS; ims++) {
10985            if (in.readInt() != 0) {
10986                long kmstName = in.readLong();
10987                getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
10988            }
10989        }
10990
10991        final int NU = in.readInt();
10992        if (NU > 10000) {
10993            throw new ParcelFormatException("File corrupt: too many uids " + NU);
10994        }
10995        for (int iu = 0; iu < NU; iu++) {
10996            int uid = in.readInt();
10997            Uid u = new Uid(this, uid);
10998            mUidStats.put(uid, u);
10999
11000            u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
11001
11002            u.mWifiRunning = false;
11003            if (in.readInt() != 0) {
11004                u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
11005            }
11006            u.mFullWifiLockOut = false;
11007            if (in.readInt() != 0) {
11008                u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
11009            }
11010            u.mWifiScanStarted = false;
11011            if (in.readInt() != 0) {
11012                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
11013            }
11014            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
11015            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
11016                if (in.readInt() != 0) {
11017                    u.makeWifiBatchedScanBin(i, null);
11018                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
11019                }
11020            }
11021            u.mWifiMulticastEnabled = false;
11022            if (in.readInt() != 0) {
11023                u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
11024            }
11025            if (in.readInt() != 0) {
11026                u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
11027            }
11028            if (in.readInt() != 0) {
11029                u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
11030            }
11031            if (in.readInt() != 0) {
11032                u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
11033            }
11034            if (in.readInt() != 0) {
11035                u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
11036            }
11037            if (in.readInt() != 0) {
11038                u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
11039            }
11040            if (in.readInt() != 0) {
11041                u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
11042            }
11043            if (in.readInt() != 0) {
11044                u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
11045            }
11046            u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
11047            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
11048                if (in.readInt() != 0) {
11049                    u.makeProcessState(i, null);
11050                    u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
11051                }
11052            }
11053            if (in.readInt() != 0) {
11054                u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
11055            }
11056
11057            if (in.readInt() != 0) {
11058                if (u.mUserActivityCounters == null) {
11059                    u.initUserActivityLocked();
11060                }
11061                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
11062                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
11063                }
11064            }
11065
11066            if (in.readInt() != 0) {
11067                if (u.mNetworkByteActivityCounters == null) {
11068                    u.initNetworkActivityLocked();
11069                }
11070                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11071                    u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
11072                    u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
11073                }
11074                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
11075                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
11076            }
11077
11078            u.mUserCpuTime.readSummaryFromParcelLocked(in);
11079            u.mSystemCpuTime.readSummaryFromParcelLocked(in);
11080
11081            if (in.readInt() != 0) {
11082                final int numClusters = in.readInt();
11083                if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
11084                    throw new ParcelFormatException("Incompatible cpu cluster arrangement");
11085                }
11086
11087                u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
11088                for (int cluster = 0; cluster < numClusters; cluster++) {
11089                    if (in.readInt() != 0) {
11090                        final int NSB = in.readInt();
11091                        if (mPowerProfile != null &&
11092                                mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
11093                            throw new ParcelFormatException("File corrupt: too many speed bins " +
11094                                    NSB);
11095                        }
11096
11097                        u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB];
11098                        for (int speed = 0; speed < NSB; speed++) {
11099                            if (in.readInt() != 0) {
11100                                u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter(
11101                                        mOnBatteryTimeBase);
11102                                u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in);
11103                            }
11104                        }
11105                    } else {
11106                        u.mCpuClusterSpeed[cluster] = null;
11107                    }
11108                }
11109            } else {
11110                u.mCpuClusterSpeed = null;
11111            }
11112
11113            if (in.readInt() != 0) {
11114                u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
11115                u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
11116            } else {
11117                u.mMobileRadioApWakeupCount = null;
11118            }
11119
11120            if (in.readInt() != 0) {
11121                u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
11122                u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
11123            } else {
11124                u.mWifiRadioApWakeupCount = null;
11125            }
11126
11127            int NW = in.readInt();
11128            if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
11129                throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
11130            }
11131            for (int iw = 0; iw < NW; iw++) {
11132                String wlName = in.readString();
11133                u.readWakeSummaryFromParcelLocked(wlName, in);
11134            }
11135
11136            int NS = in.readInt();
11137            if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
11138                throw new ParcelFormatException("File corrupt: too many syncs " + NS);
11139            }
11140            for (int is = 0; is < NS; is++) {
11141                String name = in.readString();
11142                u.readSyncSummaryFromParcelLocked(name, in);
11143            }
11144
11145            int NJ = in.readInt();
11146            if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
11147                throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
11148            }
11149            for (int ij = 0; ij < NJ; ij++) {
11150                String name = in.readString();
11151                u.readJobSummaryFromParcelLocked(name, in);
11152            }
11153
11154            int NP = in.readInt();
11155            if (NP > 1000) {
11156                throw new ParcelFormatException("File corrupt: too many sensors " + NP);
11157            }
11158            for (int is = 0; is < NP; is++) {
11159                int seNumber = in.readInt();
11160                if (in.readInt() != 0) {
11161                    u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
11162                }
11163            }
11164
11165            NP = in.readInt();
11166            if (NP > 1000) {
11167                throw new ParcelFormatException("File corrupt: too many processes " + NP);
11168            }
11169            for (int ip = 0; ip < NP; ip++) {
11170                String procName = in.readString();
11171                Uid.Proc p = u.getProcessStatsLocked(procName);
11172                p.mUserTime = p.mLoadedUserTime = in.readLong();
11173                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
11174                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
11175                p.mStarts = p.mLoadedStarts = in.readInt();
11176                p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
11177                p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
11178                p.readExcessivePowerFromParcelLocked(in);
11179            }
11180
11181            NP = in.readInt();
11182            if (NP > 10000) {
11183                throw new ParcelFormatException("File corrupt: too many packages " + NP);
11184            }
11185            for (int ip = 0; ip < NP; ip++) {
11186                String pkgName = in.readString();
11187                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
11188                final int NWA = in.readInt();
11189                if (NWA > 1000) {
11190                    throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
11191                }
11192                p.mWakeupAlarms.clear();
11193                for (int iwa=0; iwa<NWA; iwa++) {
11194                    String tag = in.readString();
11195                    Counter c = new Counter(mOnBatteryTimeBase);
11196                    c.readSummaryFromParcelLocked(in);
11197                    p.mWakeupAlarms.put(tag, c);
11198                }
11199                NS = in.readInt();
11200                if (NS > 1000) {
11201                    throw new ParcelFormatException("File corrupt: too many services " + NS);
11202                }
11203                for (int is = 0; is < NS; is++) {
11204                    String servName = in.readString();
11205                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
11206                    s.mStartTime = s.mLoadedStartTime = in.readLong();
11207                    s.mStarts = s.mLoadedStarts = in.readInt();
11208                    s.mLaunches = s.mLoadedLaunches = in.readInt();
11209                }
11210            }
11211        }
11212    }
11213
11214    /**
11215     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
11216     * disk.  This format does not allow a lossless round-trip.
11217     *
11218     * @param out the Parcel to be written to.
11219     */
11220    public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
11221        pullPendingStateUpdatesLocked();
11222
11223        // Pull the clock time.  This may update the time and make a new history entry
11224        // if we had originally pulled a time before the RTC was set.
11225        long startClockTime = getStartClockTime();
11226
11227        final long NOW_SYS = mClocks.uptimeMillis() * 1000;
11228        final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
11229
11230        out.writeInt(VERSION);
11231
11232        writeHistory(out, inclHistory, true);
11233
11234        out.writeInt(mStartCount);
11235        out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
11236        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
11237        out.writeLong(startClockTime);
11238        out.writeString(mStartPlatformVersion);
11239        out.writeString(mEndPlatformVersion);
11240        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
11241        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
11242        out.writeInt(mDischargeUnplugLevel);
11243        out.writeInt(mDischargePlugLevel);
11244        out.writeInt(mDischargeCurrentLevel);
11245        out.writeInt(mCurrentBatteryLevel);
11246        out.writeInt(mEstimatedBatteryCapacity);
11247        out.writeInt(mMinLearnedBatteryCapacity);
11248        out.writeInt(mMaxLearnedBatteryCapacity);
11249        out.writeInt(getLowDischargeAmountSinceCharge());
11250        out.writeInt(getHighDischargeAmountSinceCharge());
11251        out.writeInt(getDischargeAmountScreenOnSinceCharge());
11252        out.writeInt(getDischargeAmountScreenOffSinceCharge());
11253        mDischargeStepTracker.writeToParcel(out);
11254        mChargeStepTracker.writeToParcel(out);
11255        mDailyDischargeStepTracker.writeToParcel(out);
11256        mDailyChargeStepTracker.writeToParcel(out);
11257        mDischargeCounter.writeSummaryFromParcelLocked(out);
11258        mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
11259        if (mDailyPackageChanges != null) {
11260            final int NPKG = mDailyPackageChanges.size();
11261            out.writeInt(NPKG);
11262            for (int i=0; i<NPKG; i++) {
11263                PackageChange pc = mDailyPackageChanges.get(i);
11264                out.writeString(pc.mPackageName);
11265                out.writeInt(pc.mUpdate ? 1 : 0);
11266                out.writeInt(pc.mVersionCode);
11267            }
11268        } else {
11269            out.writeInt(0);
11270        }
11271        out.writeLong(mDailyStartTime);
11272        out.writeLong(mNextMinDailyDeadline);
11273        out.writeLong(mNextMaxDailyDeadline);
11274
11275        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11276        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11277            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11278        }
11279        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11280        mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11281        out.writeLong(mLongestLightIdleTime);
11282        out.writeLong(mLongestFullIdleTime);
11283        mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11284        mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11285        mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11286        mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11287        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11288        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11289            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11290        }
11291        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11292        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11293            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11294        }
11295        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11296            mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
11297            mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
11298        }
11299        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11300        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11301        mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
11302        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
11303        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
11304        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11305        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11306        for (int i=0; i<NUM_WIFI_STATES; i++) {
11307            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11308        }
11309        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11310            mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11311        }
11312        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11313            mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11314        }
11315        mWifiActivity.writeSummaryToParcel(out);
11316        mBluetoothActivity.writeSummaryToParcel(out);
11317        mModemActivity.writeSummaryToParcel(out);
11318        out.writeInt(mHasWifiReporting ? 1 : 0);
11319        out.writeInt(mHasBluetoothReporting ? 1 : 0);
11320        out.writeInt(mHasModemReporting ? 1 : 0);
11321
11322        out.writeInt(mNumConnectivityChange);
11323        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11324        mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11325        mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11326
11327        out.writeInt(mKernelWakelockStats.size());
11328        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11329            Timer kwlt = ent.getValue();
11330            if (kwlt != null) {
11331                out.writeInt(1);
11332                out.writeString(ent.getKey());
11333                kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11334            } else {
11335                out.writeInt(0);
11336            }
11337        }
11338
11339        out.writeInt(mWakeupReasonStats.size());
11340        for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
11341            SamplingTimer timer = ent.getValue();
11342            if (timer != null) {
11343                out.writeInt(1);
11344                out.writeString(ent.getKey());
11345                timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11346            } else {
11347                out.writeInt(0);
11348            }
11349        }
11350
11351        out.writeInt(mKernelMemoryStats.size());
11352        for (int i = 0; i < mKernelMemoryStats.size(); i++) {
11353            Timer kmt = mKernelMemoryStats.valueAt(i);
11354            if (kmt != null) {
11355                out.writeInt(1);
11356                out.writeLong(mKernelMemoryStats.keyAt(i));
11357                kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11358            } else {
11359                out.writeInt(0);
11360            }
11361        }
11362
11363        final int NU = mUidStats.size();
11364        out.writeInt(NU);
11365        for (int iu = 0; iu < NU; iu++) {
11366            out.writeInt(mUidStats.keyAt(iu));
11367            Uid u = mUidStats.valueAt(iu);
11368
11369            u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
11370
11371            if (u.mWifiRunningTimer != null) {
11372                out.writeInt(1);
11373                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11374            } else {
11375                out.writeInt(0);
11376            }
11377            if (u.mFullWifiLockTimer != null) {
11378                out.writeInt(1);
11379                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11380            } else {
11381                out.writeInt(0);
11382            }
11383            if (u.mWifiScanTimer != null) {
11384                out.writeInt(1);
11385                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11386            } else {
11387                out.writeInt(0);
11388            }
11389            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
11390                if (u.mWifiBatchedScanTimer[i] != null) {
11391                    out.writeInt(1);
11392                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11393                } else {
11394                    out.writeInt(0);
11395                }
11396            }
11397            if (u.mWifiMulticastTimer != null) {
11398                out.writeInt(1);
11399                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11400            } else {
11401                out.writeInt(0);
11402            }
11403            if (u.mAudioTurnedOnTimer != null) {
11404                out.writeInt(1);
11405                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11406            } else {
11407                out.writeInt(0);
11408            }
11409            if (u.mVideoTurnedOnTimer != null) {
11410                out.writeInt(1);
11411                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11412            } else {
11413                out.writeInt(0);
11414            }
11415            if (u.mFlashlightTurnedOnTimer != null) {
11416                out.writeInt(1);
11417                u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11418            } else {
11419                out.writeInt(0);
11420            }
11421            if (u.mCameraTurnedOnTimer != null) {
11422                out.writeInt(1);
11423                u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11424            } else {
11425                out.writeInt(0);
11426            }
11427            if (u.mForegroundActivityTimer != null) {
11428                out.writeInt(1);
11429                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11430            } else {
11431                out.writeInt(0);
11432            }
11433            if (u.mBluetoothScanTimer != null) {
11434                out.writeInt(1);
11435                u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11436            } else {
11437                out.writeInt(0);
11438            }
11439            if (u.mBluetoothScanResultCounter != null) {
11440                out.writeInt(1);
11441                u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
11442            } else {
11443                out.writeInt(0);
11444            }
11445            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
11446                if (u.mProcessStateTimer[i] != null) {
11447                    out.writeInt(1);
11448                    u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11449                } else {
11450                    out.writeInt(0);
11451                }
11452            }
11453            if (u.mVibratorOnTimer != null) {
11454                out.writeInt(1);
11455                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11456            } else {
11457                out.writeInt(0);
11458            }
11459
11460            if (u.mUserActivityCounters == null) {
11461                out.writeInt(0);
11462            } else {
11463                out.writeInt(1);
11464                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
11465                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
11466                }
11467            }
11468
11469            if (u.mNetworkByteActivityCounters == null) {
11470                out.writeInt(0);
11471            } else {
11472                out.writeInt(1);
11473                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11474                    u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
11475                    u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
11476                }
11477                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
11478                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
11479            }
11480
11481            u.mUserCpuTime.writeSummaryFromParcelLocked(out);
11482            u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
11483
11484            if (u.mCpuClusterSpeed != null) {
11485                out.writeInt(1);
11486                out.writeInt(u.mCpuClusterSpeed.length);
11487                for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) {
11488                    if (cpuSpeeds != null) {
11489                        out.writeInt(1);
11490                        out.writeInt(cpuSpeeds.length);
11491                        for (LongSamplingCounter c : cpuSpeeds) {
11492                            if (c != null) {
11493                                out.writeInt(1);
11494                                c.writeSummaryFromParcelLocked(out);
11495                            } else {
11496                                out.writeInt(0);
11497                            }
11498                        }
11499                    } else {
11500                        out.writeInt(0);
11501                    }
11502                }
11503            } else {
11504                out.writeInt(0);
11505            }
11506
11507            if (u.mMobileRadioApWakeupCount != null) {
11508                out.writeInt(1);
11509                u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
11510            } else {
11511                out.writeInt(0);
11512            }
11513
11514            if (u.mWifiRadioApWakeupCount != null) {
11515                out.writeInt(1);
11516                u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
11517            } else {
11518                out.writeInt(0);
11519            }
11520
11521            final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
11522            int NW = wakeStats.size();
11523            out.writeInt(NW);
11524            for (int iw=0; iw<NW; iw++) {
11525                out.writeString(wakeStats.keyAt(iw));
11526                Uid.Wakelock wl = wakeStats.valueAt(iw);
11527                if (wl.mTimerFull != null) {
11528                    out.writeInt(1);
11529                    wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11530                } else {
11531                    out.writeInt(0);
11532                }
11533                if (wl.mTimerPartial != null) {
11534                    out.writeInt(1);
11535                    wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11536                } else {
11537                    out.writeInt(0);
11538                }
11539                if (wl.mTimerWindow != null) {
11540                    out.writeInt(1);
11541                    wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11542                } else {
11543                    out.writeInt(0);
11544                }
11545                if (wl.mTimerDraw != null) {
11546                    out.writeInt(1);
11547                    wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11548                } else {
11549                    out.writeInt(0);
11550                }
11551            }
11552
11553            final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
11554            int NS = syncStats.size();
11555            out.writeInt(NS);
11556            for (int is=0; is<NS; is++) {
11557                out.writeString(syncStats.keyAt(is));
11558                syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11559            }
11560
11561            final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
11562            int NJ = jobStats.size();
11563            out.writeInt(NJ);
11564            for (int ij=0; ij<NJ; ij++) {
11565                out.writeString(jobStats.keyAt(ij));
11566                jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11567            }
11568
11569            int NSE = u.mSensorStats.size();
11570            out.writeInt(NSE);
11571            for (int ise=0; ise<NSE; ise++) {
11572                out.writeInt(u.mSensorStats.keyAt(ise));
11573                Uid.Sensor se = u.mSensorStats.valueAt(ise);
11574                if (se.mTimer != null) {
11575                    out.writeInt(1);
11576                    se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11577                } else {
11578                    out.writeInt(0);
11579                }
11580            }
11581
11582            int NP = u.mProcessStats.size();
11583            out.writeInt(NP);
11584            for (int ip=0; ip<NP; ip++) {
11585                out.writeString(u.mProcessStats.keyAt(ip));
11586                Uid.Proc ps = u.mProcessStats.valueAt(ip);
11587                out.writeLong(ps.mUserTime);
11588                out.writeLong(ps.mSystemTime);
11589                out.writeLong(ps.mForegroundTime);
11590                out.writeInt(ps.mStarts);
11591                out.writeInt(ps.mNumCrashes);
11592                out.writeInt(ps.mNumAnrs);
11593                ps.writeExcessivePowerToParcelLocked(out);
11594            }
11595
11596            NP = u.mPackageStats.size();
11597            out.writeInt(NP);
11598            if (NP > 0) {
11599                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
11600                    : u.mPackageStats.entrySet()) {
11601                    out.writeString(ent.getKey());
11602                    Uid.Pkg ps = ent.getValue();
11603                    final int NWA = ps.mWakeupAlarms.size();
11604                    out.writeInt(NWA);
11605                    for (int iwa=0; iwa<NWA; iwa++) {
11606                        out.writeString(ps.mWakeupAlarms.keyAt(iwa));
11607                        ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
11608                    }
11609                    NS = ps.mServiceStats.size();
11610                    out.writeInt(NS);
11611                    for (int is=0; is<NS; is++) {
11612                        out.writeString(ps.mServiceStats.keyAt(is));
11613                        BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
11614                        long time = ss.getStartTimeToNowLocked(
11615                                mOnBatteryTimeBase.getUptime(NOW_SYS));
11616                        out.writeLong(time);
11617                        out.writeInt(ss.mStarts);
11618                        out.writeInt(ss.mLaunches);
11619                    }
11620                }
11621            }
11622        }
11623    }
11624
11625    public void readFromParcel(Parcel in) {
11626        readFromParcelLocked(in);
11627    }
11628
11629    void readFromParcelLocked(Parcel in) {
11630        int magic = in.readInt();
11631        if (magic != MAGIC) {
11632            throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
11633        }
11634
11635        readHistory(in, false);
11636
11637        mStartCount = in.readInt();
11638        mStartClockTime = in.readLong();
11639        mStartPlatformVersion = in.readString();
11640        mEndPlatformVersion = in.readString();
11641        mUptime = in.readLong();
11642        mUptimeStart = in.readLong();
11643        mRealtime = in.readLong();
11644        mRealtimeStart = in.readLong();
11645        mOnBattery = in.readInt() != 0;
11646        mEstimatedBatteryCapacity = in.readInt();
11647        mMinLearnedBatteryCapacity = in.readInt();
11648        mMaxLearnedBatteryCapacity = in.readInt();
11649        mOnBatteryInternal = false; // we are no longer really running.
11650        mOnBatteryTimeBase.readFromParcel(in);
11651        mOnBatteryScreenOffTimeBase.readFromParcel(in);
11652
11653        mScreenState = Display.STATE_UNKNOWN;
11654        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
11655        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11656            mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
11657                    mOnBatteryTimeBase, in);
11658        }
11659        mInteractive = false;
11660        mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
11661        mPhoneOn = false;
11662        mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
11663                mOnBatteryTimeBase, in);
11664        mLongestLightIdleTime = in.readLong();
11665        mLongestFullIdleTime = in.readLong();
11666        mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
11667                mOnBatteryTimeBase, in);
11668        mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
11669                mOnBatteryTimeBase, in);
11670        mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
11671                mOnBatteryTimeBase, in);
11672        mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
11673        mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
11674        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11675            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
11676                    null, mOnBatteryTimeBase, in);
11677        }
11678        mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
11679                mOnBatteryTimeBase, in);
11680        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11681            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
11682                    null, mOnBatteryTimeBase, in);
11683        }
11684        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11685            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
11686            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
11687        }
11688        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
11689        mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
11690                mOnBatteryTimeBase, in);
11691        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
11692                mOnBatteryTimeBase, in);
11693        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
11694        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
11695        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
11696        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
11697        mWifiOn = false;
11698        mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
11699        mGlobalWifiRunning = false;
11700        mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
11701                mOnBatteryTimeBase, in);
11702        for (int i=0; i<NUM_WIFI_STATES; i++) {
11703            mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
11704                    null, mOnBatteryTimeBase, in);
11705        }
11706        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11707            mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
11708                    null, mOnBatteryTimeBase, in);
11709        }
11710        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11711            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
11712                    null, mOnBatteryTimeBase, in);
11713        }
11714
11715        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11716                NUM_WIFI_TX_LEVELS, in);
11717        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11718                NUM_BT_TX_LEVELS, in);
11719        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11720                ModemActivityInfo.TX_POWER_LEVELS, in);
11721        mHasWifiReporting = in.readInt() != 0;
11722        mHasBluetoothReporting = in.readInt() != 0;
11723        mHasModemReporting = in.readInt() != 0;
11724
11725        mNumConnectivityChange = in.readInt();
11726        mLoadedNumConnectivityChange = in.readInt();
11727        mUnpluggedNumConnectivityChange = in.readInt();
11728        mAudioOnNesting = 0;
11729        mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
11730        mVideoOnNesting = 0;
11731        mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
11732        mFlashlightOnNesting = 0;
11733        mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
11734        mCameraOnNesting = 0;
11735        mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
11736        mBluetoothScanNesting = 0;
11737        mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
11738        mDischargeUnplugLevel = in.readInt();
11739        mDischargePlugLevel = in.readInt();
11740        mDischargeCurrentLevel = in.readInt();
11741        mCurrentBatteryLevel = in.readInt();
11742        mLowDischargeAmountSinceCharge = in.readInt();
11743        mHighDischargeAmountSinceCharge = in.readInt();
11744        mDischargeAmountScreenOn = in.readInt();
11745        mDischargeAmountScreenOnSinceCharge = in.readInt();
11746        mDischargeAmountScreenOff = in.readInt();
11747        mDischargeAmountScreenOffSinceCharge = in.readInt();
11748        mDischargeStepTracker.readFromParcel(in);
11749        mChargeStepTracker.readFromParcel(in);
11750        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
11751        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
11752        mLastWriteTime = in.readLong();
11753
11754        mKernelWakelockStats.clear();
11755        int NKW = in.readInt();
11756        for (int ikw = 0; ikw < NKW; ikw++) {
11757            if (in.readInt() != 0) {
11758                String wakelockName = in.readString();
11759                SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
11760                mKernelWakelockStats.put(wakelockName, kwlt);
11761            }
11762        }
11763
11764        mWakeupReasonStats.clear();
11765        int NWR = in.readInt();
11766        for (int iwr = 0; iwr < NWR; iwr++) {
11767            if (in.readInt() != 0) {
11768                String reasonName = in.readString();
11769                SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
11770                mWakeupReasonStats.put(reasonName, timer);
11771            }
11772        }
11773
11774        mKernelMemoryStats.clear();
11775        int nmt = in.readInt();
11776        for (int imt = 0; imt < nmt; imt++) {
11777            if (in.readInt() != 0) {
11778                Long bucket = in.readLong();
11779                SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
11780                mKernelMemoryStats.put(bucket, kmt);
11781            }
11782        }
11783
11784        mPartialTimers.clear();
11785        mFullTimers.clear();
11786        mWindowTimers.clear();
11787        mWifiRunningTimers.clear();
11788        mFullWifiLockTimers.clear();
11789        mWifiScanTimers.clear();
11790        mWifiBatchedScanTimers.clear();
11791        mWifiMulticastTimers.clear();
11792        mAudioTurnedOnTimers.clear();
11793        mVideoTurnedOnTimers.clear();
11794        mFlashlightTurnedOnTimers.clear();
11795        mCameraTurnedOnTimers.clear();
11796
11797        int numUids = in.readInt();
11798        mUidStats.clear();
11799        for (int i = 0; i < numUids; i++) {
11800            int uid = in.readInt();
11801            Uid u = new Uid(this, uid);
11802            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
11803            mUidStats.append(uid, u);
11804        }
11805    }
11806
11807    public void writeToParcel(Parcel out, int flags) {
11808        writeToParcelLocked(out, true, flags);
11809    }
11810
11811    public void writeToParcelWithoutUids(Parcel out, int flags) {
11812        writeToParcelLocked(out, false, flags);
11813    }
11814
11815    @SuppressWarnings("unused")
11816    void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
11817        // Need to update with current kernel wake lock counts.
11818        pullPendingStateUpdatesLocked();
11819
11820        // Pull the clock time.  This may update the time and make a new history entry
11821        // if we had originally pulled a time before the RTC was set.
11822        long startClockTime = getStartClockTime();
11823
11824        final long uSecUptime = mClocks.uptimeMillis() * 1000;
11825        final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
11826        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
11827        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
11828
11829        out.writeInt(MAGIC);
11830
11831        writeHistory(out, true, false);
11832
11833        out.writeInt(mStartCount);
11834        out.writeLong(startClockTime);
11835        out.writeString(mStartPlatformVersion);
11836        out.writeString(mEndPlatformVersion);
11837        out.writeLong(mUptime);
11838        out.writeLong(mUptimeStart);
11839        out.writeLong(mRealtime);
11840        out.writeLong(mRealtimeStart);
11841        out.writeInt(mOnBattery ? 1 : 0);
11842        out.writeInt(mEstimatedBatteryCapacity);
11843        out.writeInt(mMinLearnedBatteryCapacity);
11844        out.writeInt(mMaxLearnedBatteryCapacity);
11845        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
11846        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
11847
11848        mScreenOnTimer.writeToParcel(out, uSecRealtime);
11849        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11850            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
11851        }
11852        mInteractiveTimer.writeToParcel(out, uSecRealtime);
11853        mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
11854        out.writeLong(mLongestLightIdleTime);
11855        out.writeLong(mLongestFullIdleTime);
11856        mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
11857        mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
11858        mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
11859        mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
11860        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
11861        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11862            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
11863        }
11864        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
11865        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11866            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
11867        }
11868        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11869            mNetworkByteActivityCounters[i].writeToParcel(out);
11870            mNetworkPacketActivityCounters[i].writeToParcel(out);
11871        }
11872        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
11873        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
11874        mMobileRadioActiveAdjustedTime.writeToParcel(out);
11875        mMobileRadioActiveUnknownTime.writeToParcel(out);
11876        mMobileRadioActiveUnknownCount.writeToParcel(out);
11877        mWifiOnTimer.writeToParcel(out, uSecRealtime);
11878        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
11879        for (int i=0; i<NUM_WIFI_STATES; i++) {
11880            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
11881        }
11882        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11883            mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
11884        }
11885        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11886            mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
11887        }
11888        mWifiActivity.writeToParcel(out, 0);
11889        mBluetoothActivity.writeToParcel(out, 0);
11890        mModemActivity.writeToParcel(out, 0);
11891        out.writeInt(mHasWifiReporting ? 1 : 0);
11892        out.writeInt(mHasBluetoothReporting ? 1 : 0);
11893        out.writeInt(mHasModemReporting ? 1 : 0);
11894
11895        out.writeInt(mNumConnectivityChange);
11896        out.writeInt(mLoadedNumConnectivityChange);
11897        out.writeInt(mUnpluggedNumConnectivityChange);
11898        mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
11899        mCameraOnTimer.writeToParcel(out, uSecRealtime);
11900        mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
11901        out.writeInt(mDischargeUnplugLevel);
11902        out.writeInt(mDischargePlugLevel);
11903        out.writeInt(mDischargeCurrentLevel);
11904        out.writeInt(mCurrentBatteryLevel);
11905        out.writeInt(mLowDischargeAmountSinceCharge);
11906        out.writeInt(mHighDischargeAmountSinceCharge);
11907        out.writeInt(mDischargeAmountScreenOn);
11908        out.writeInt(mDischargeAmountScreenOnSinceCharge);
11909        out.writeInt(mDischargeAmountScreenOff);
11910        out.writeInt(mDischargeAmountScreenOffSinceCharge);
11911        mDischargeStepTracker.writeToParcel(out);
11912        mChargeStepTracker.writeToParcel(out);
11913        mDischargeCounter.writeToParcel(out);
11914        mDischargeScreenOffCounter.writeToParcel(out);
11915        out.writeLong(mLastWriteTime);
11916
11917        if (inclUids) {
11918            out.writeInt(mKernelWakelockStats.size());
11919            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11920                SamplingTimer kwlt = ent.getValue();
11921                if (kwlt != null) {
11922                    out.writeInt(1);
11923                    out.writeString(ent.getKey());
11924                    kwlt.writeToParcel(out, uSecRealtime);
11925                } else {
11926                    out.writeInt(0);
11927                }
11928            }
11929            out.writeInt(mWakeupReasonStats.size());
11930            for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
11931                SamplingTimer timer = ent.getValue();
11932                if (timer != null) {
11933                    out.writeInt(1);
11934                    out.writeString(ent.getKey());
11935                    timer.writeToParcel(out, uSecRealtime);
11936                } else {
11937                    out.writeInt(0);
11938                }
11939            }
11940        } else {
11941            out.writeInt(0);
11942        }
11943
11944        out.writeInt(mKernelMemoryStats.size());
11945        for (int i = 0; i < mKernelMemoryStats.size(); i++) {
11946            SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
11947            if (kmt != null) {
11948                out.writeInt(1);
11949                out.writeLong(mKernelMemoryStats.keyAt(i));
11950                kmt.writeToParcel(out, uSecRealtime);
11951            } else {
11952                out.writeInt(0);
11953            }
11954        }
11955
11956        if (inclUids) {
11957            int size = mUidStats.size();
11958            out.writeInt(size);
11959            for (int i = 0; i < size; i++) {
11960                out.writeInt(mUidStats.keyAt(i));
11961                Uid uid = mUidStats.valueAt(i);
11962
11963                uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
11964            }
11965        } else {
11966            out.writeInt(0);
11967        }
11968    }
11969
11970    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
11971        new Parcelable.Creator<BatteryStatsImpl>() {
11972        public BatteryStatsImpl createFromParcel(Parcel in) {
11973            return new BatteryStatsImpl(in);
11974        }
11975
11976        public BatteryStatsImpl[] newArray(int size) {
11977            return new BatteryStatsImpl[size];
11978        }
11979    };
11980
11981    public void prepareForDumpLocked() {
11982        // Need to retrieve current kernel wake lock stats before printing.
11983        pullPendingStateUpdatesLocked();
11984
11985        // Pull the clock time.  This may update the time and make a new history entry
11986        // if we had originally pulled a time before the RTC was set.
11987        getStartClockTime();
11988    }
11989
11990    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
11991        if (DEBUG) {
11992            pw.println("mOnBatteryTimeBase:");
11993            mOnBatteryTimeBase.dump(pw, "  ");
11994            pw.println("mOnBatteryScreenOffTimeBase:");
11995            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
11996            Printer pr = new PrintWriterPrinter(pw);
11997            pr.println("*** Screen timer:");
11998            mScreenOnTimer.logState(pr, "  ");
11999            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
12000                pr.println("*** Screen brightness #" + i + ":");
12001                mScreenBrightnessTimer[i].logState(pr, "  ");
12002            }
12003            pr.println("*** Interactive timer:");
12004            mInteractiveTimer.logState(pr, "  ");
12005            pr.println("*** Power save mode timer:");
12006            mPowerSaveModeEnabledTimer.logState(pr, "  ");
12007            pr.println("*** Device idle mode light timer:");
12008            mDeviceIdleModeLightTimer.logState(pr, "  ");
12009            pr.println("*** Device idle mode full timer:");
12010            mDeviceIdleModeFullTimer.logState(pr, "  ");
12011            pr.println("*** Device light idling timer:");
12012            mDeviceLightIdlingTimer.logState(pr, "  ");
12013            pr.println("*** Device idling timer:");
12014            mDeviceIdlingTimer.logState(pr, "  ");
12015            pr.println("*** Phone timer:");
12016            mPhoneOnTimer.logState(pr, "  ");
12017            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
12018                pr.println("*** Phone signal strength #" + i + ":");
12019                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
12020            }
12021            pr.println("*** Signal scanning :");
12022            mPhoneSignalScanningTimer.logState(pr, "  ");
12023            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
12024                pr.println("*** Data connection type #" + i + ":");
12025                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
12026            }
12027            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
12028            pr.println("*** Mobile network active timer:");
12029            mMobileRadioActiveTimer.logState(pr, "  ");
12030            pr.println("*** Mobile network active adjusted timer:");
12031            mMobileRadioActiveAdjustedTime.logState(pr, "  ");
12032            pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
12033            pr.println("*** Wifi timer:");
12034            mWifiOnTimer.logState(pr, "  ");
12035            pr.println("*** WifiRunning timer:");
12036            mGlobalWifiRunningTimer.logState(pr, "  ");
12037            for (int i=0; i<NUM_WIFI_STATES; i++) {
12038                pr.println("*** Wifi state #" + i + ":");
12039                mWifiStateTimer[i].logState(pr, "  ");
12040            }
12041            for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
12042                pr.println("*** Wifi suppl state #" + i + ":");
12043                mWifiSupplStateTimer[i].logState(pr, "  ");
12044            }
12045            for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
12046                pr.println("*** Wifi signal strength #" + i + ":");
12047                mWifiSignalStrengthsTimer[i].logState(pr, "  ");
12048            }
12049            pr.println("*** Flashlight timer:");
12050            mFlashlightOnTimer.logState(pr, "  ");
12051            pr.println("*** Camera timer:");
12052            mCameraOnTimer.logState(pr, "  ");
12053        }
12054        super.dumpLocked(context, pw, flags, reqUid, histStart);
12055    }
12056}
12057