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