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