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