BatteryStatsImpl.java revision d4abd1eeb01187fa2ef78b64ae4f493a7bb3563f
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 = 154 + (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[][] mCpuClusterSpeed;
5467
5468        /**
5469         * The statistics we have collected for this uid's wake locks.
5470         */
5471        final OverflowArrayMap<Wakelock> mWakelockStats;
5472
5473        /**
5474         * The statistics we have collected for this uid's syncs.
5475         */
5476        final OverflowArrayMap<StopwatchTimer> mSyncStats;
5477
5478        /**
5479         * The statistics we have collected for this uid's jobs.
5480         */
5481        final OverflowArrayMap<DualTimer> mJobStats;
5482
5483        /**
5484         * The statistics we have collected for this uid's sensor activations.
5485         */
5486        final SparseArray<Sensor> mSensorStats = new SparseArray<>();
5487
5488        /**
5489         * The statistics we have collected for this uid's processes.
5490         */
5491        final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
5492
5493        /**
5494         * The statistics we have collected for this uid's processes.
5495         */
5496        final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
5497
5498        /**
5499         * The transient wake stats we have collected for this uid's pids.
5500         */
5501        final SparseArray<Pid> mPids = new SparseArray<>();
5502
5503        public Uid(BatteryStatsImpl bsi, int uid) {
5504            mBsi = bsi;
5505            mUid = uid;
5506
5507            mOnBatteryBackgroundTimeBase = new TimeBase();
5508            mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
5509                    mBsi.mClocks.elapsedRealtime() * 1000);
5510
5511            mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5512            mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5513
5514            mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
5515                @Override public Wakelock instantiateObject() {
5516                    return new Wakelock(mBsi, Uid.this);
5517                }
5518            };
5519            mSyncStats = mBsi.new OverflowArrayMap<StopwatchTimer>(uid) {
5520                @Override public StopwatchTimer instantiateObject() {
5521                    return new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null,
5522                            mBsi.mOnBatteryTimeBase);
5523                }
5524            };
5525            mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
5526                @Override public DualTimer instantiateObject() {
5527                    return new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
5528                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
5529                }
5530            };
5531
5532            mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
5533                    mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
5534            mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
5535                    mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
5536            mWifiScanTimer = new DualTimer(mBsi.mClocks, this, WIFI_SCAN,
5537                    mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
5538            mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
5539            mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
5540                    mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
5541            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
5542        }
5543
5544        @Override
5545        public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
5546            return mWakelockStats.getMap();
5547        }
5548
5549        @Override
5550        public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
5551            return mSyncStats.getMap();
5552        }
5553
5554        @Override
5555        public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
5556            return mJobStats.getMap();
5557        }
5558
5559        @Override
5560        public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
5561            return mSensorStats;
5562        }
5563
5564        @Override
5565        public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
5566            return mProcessStats;
5567        }
5568
5569        @Override
5570        public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
5571            return mPackageStats;
5572        }
5573
5574        @Override
5575        public int getUid() {
5576            return mUid;
5577        }
5578
5579        @Override
5580        public void noteWifiRunningLocked(long elapsedRealtimeMs) {
5581            if (!mWifiRunning) {
5582                mWifiRunning = true;
5583                if (mWifiRunningTimer == null) {
5584                    mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
5585                            mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
5586                }
5587                mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
5588            }
5589        }
5590
5591        @Override
5592        public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
5593            if (mWifiRunning) {
5594                mWifiRunning = false;
5595                mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
5596            }
5597        }
5598
5599        @Override
5600        public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
5601            if (!mFullWifiLockOut) {
5602                mFullWifiLockOut = true;
5603                if (mFullWifiLockTimer == null) {
5604                    mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
5605                            mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
5606                }
5607                mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
5608            }
5609        }
5610
5611        @Override
5612        public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
5613            if (mFullWifiLockOut) {
5614                mFullWifiLockOut = false;
5615                mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
5616            }
5617        }
5618
5619        @Override
5620        public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
5621            if (!mWifiScanStarted) {
5622                mWifiScanStarted = true;
5623                if (mWifiScanTimer == null) {
5624                    mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
5625                            mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase,
5626                            mOnBatteryBackgroundTimeBase);
5627                }
5628                mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
5629            }
5630        }
5631
5632        @Override
5633        public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
5634            if (mWifiScanStarted) {
5635                mWifiScanStarted = false;
5636                mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
5637            }
5638        }
5639
5640        @Override
5641        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
5642            int bin = 0;
5643            while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
5644                csph = csph >> 3;
5645                bin++;
5646            }
5647
5648            if (mWifiBatchedScanBinStarted == bin) return;
5649
5650            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
5651                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
5652                        stopRunningLocked(elapsedRealtimeMs);
5653            }
5654            mWifiBatchedScanBinStarted = bin;
5655            if (mWifiBatchedScanTimer[bin] == null) {
5656                makeWifiBatchedScanBin(bin, null);
5657            }
5658            mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
5659        }
5660
5661        @Override
5662        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
5663            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
5664                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
5665                        stopRunningLocked(elapsedRealtimeMs);
5666                mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
5667            }
5668        }
5669
5670        @Override
5671        public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
5672            if (!mWifiMulticastEnabled) {
5673                mWifiMulticastEnabled = true;
5674                if (mWifiMulticastTimer == null) {
5675                    mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
5676                            WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
5677                }
5678                mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
5679            }
5680        }
5681
5682        @Override
5683        public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
5684            if (mWifiMulticastEnabled) {
5685                mWifiMulticastEnabled = false;
5686                mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
5687            }
5688        }
5689
5690        @Override
5691        public ControllerActivityCounter getWifiControllerActivity() {
5692            return mWifiControllerActivity;
5693        }
5694
5695        @Override
5696        public ControllerActivityCounter getBluetoothControllerActivity() {
5697            return mBluetoothControllerActivity;
5698        }
5699
5700        @Override
5701        public ControllerActivityCounter getModemControllerActivity() {
5702            return mModemControllerActivity;
5703        }
5704
5705        public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
5706            if (mWifiControllerActivity == null) {
5707                mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
5708                        NUM_BT_TX_LEVELS);
5709            }
5710            return mWifiControllerActivity;
5711        }
5712
5713        public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
5714            if (mBluetoothControllerActivity == null) {
5715                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
5716                        NUM_BT_TX_LEVELS);
5717            }
5718            return mBluetoothControllerActivity;
5719        }
5720
5721        public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
5722            if (mModemControllerActivity == null) {
5723                mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
5724                        ModemActivityInfo.TX_POWER_LEVELS);
5725            }
5726            return mModemControllerActivity;
5727        }
5728
5729        public StopwatchTimer createAudioTurnedOnTimerLocked() {
5730            if (mAudioTurnedOnTimer == null) {
5731                mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
5732                        mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5733            }
5734            return mAudioTurnedOnTimer;
5735        }
5736
5737        public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
5738            createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5739        }
5740
5741        public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
5742            if (mAudioTurnedOnTimer != null) {
5743                mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5744            }
5745        }
5746
5747        public void noteResetAudioLocked(long elapsedRealtimeMs) {
5748            if (mAudioTurnedOnTimer != null) {
5749                mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5750            }
5751        }
5752
5753        public StopwatchTimer createVideoTurnedOnTimerLocked() {
5754            if (mVideoTurnedOnTimer == null) {
5755                mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
5756                        mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5757            }
5758            return mVideoTurnedOnTimer;
5759        }
5760
5761        public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
5762            createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5763        }
5764
5765        public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
5766            if (mVideoTurnedOnTimer != null) {
5767                mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5768            }
5769        }
5770
5771        public void noteResetVideoLocked(long elapsedRealtimeMs) {
5772            if (mVideoTurnedOnTimer != null) {
5773                mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5774            }
5775        }
5776
5777        public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
5778            if (mFlashlightTurnedOnTimer == null) {
5779                mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
5780                        FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5781            }
5782            return mFlashlightTurnedOnTimer;
5783        }
5784
5785        public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
5786            createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5787        }
5788
5789        public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
5790            if (mFlashlightTurnedOnTimer != null) {
5791                mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5792            }
5793        }
5794
5795        public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
5796            if (mFlashlightTurnedOnTimer != null) {
5797                mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5798            }
5799        }
5800
5801        public StopwatchTimer createCameraTurnedOnTimerLocked() {
5802            if (mCameraTurnedOnTimer == null) {
5803                mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
5804                        mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5805            }
5806            return mCameraTurnedOnTimer;
5807        }
5808
5809        public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
5810            createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5811        }
5812
5813        public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
5814            if (mCameraTurnedOnTimer != null) {
5815                mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5816            }
5817        }
5818
5819        public void noteResetCameraLocked(long elapsedRealtimeMs) {
5820            if (mCameraTurnedOnTimer != null) {
5821                mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5822            }
5823        }
5824
5825        public StopwatchTimer createForegroundActivityTimerLocked() {
5826            if (mForegroundActivityTimer == null) {
5827                mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
5828                        FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
5829            }
5830            return mForegroundActivityTimer;
5831        }
5832
5833        public DualTimer createBluetoothScanTimerLocked() {
5834            if (mBluetoothScanTimer == null) {
5835                mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
5836                        mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
5837                        mOnBatteryBackgroundTimeBase);
5838            }
5839            return mBluetoothScanTimer;
5840        }
5841
5842        public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs) {
5843            createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
5844        }
5845
5846        public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs) {
5847            if (mBluetoothScanTimer != null) {
5848                mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
5849            }
5850        }
5851
5852        public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
5853            if (mBluetoothScanTimer != null) {
5854                mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
5855            }
5856        }
5857
5858        @Override
5859        public void noteActivityResumedLocked(long elapsedRealtimeMs) {
5860            // We always start, since we want multiple foreground PIDs to nest
5861            createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
5862        }
5863
5864        @Override
5865        public void noteActivityPausedLocked(long elapsedRealtimeMs) {
5866            if (mForegroundActivityTimer != null) {
5867                mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
5868            }
5869        }
5870
5871        public BatchTimer createVibratorOnTimerLocked() {
5872            if (mVibratorOnTimer == null) {
5873                mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
5874                        mBsi.mOnBatteryTimeBase);
5875            }
5876            return mVibratorOnTimer;
5877        }
5878
5879        public void noteVibratorOnLocked(long durationMillis) {
5880            createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
5881        }
5882
5883        public void noteVibratorOffLocked() {
5884            if (mVibratorOnTimer != null) {
5885                mVibratorOnTimer.abortLastDuration(mBsi);
5886            }
5887        }
5888
5889        @Override
5890        public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
5891            if (mWifiRunningTimer == null) {
5892                return 0;
5893            }
5894            return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5895        }
5896
5897        @Override
5898        public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
5899            if (mFullWifiLockTimer == null) {
5900                return 0;
5901            }
5902            return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5903        }
5904
5905        @Override
5906        public long getWifiScanTime(long elapsedRealtimeUs, int which) {
5907            if (mWifiScanTimer == null) {
5908                return 0;
5909            }
5910            return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5911        }
5912
5913        @Override
5914        public int getWifiScanCount(int which) {
5915            if (mWifiScanTimer == null) {
5916                return 0;
5917            }
5918            return mWifiScanTimer.getCountLocked(which);
5919        }
5920
5921        @Override
5922        public int getWifiScanBackgroundCount(int which) {
5923            if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
5924                return 0;
5925            }
5926            return mWifiScanTimer.getSubTimer().getCountLocked(which);
5927        }
5928
5929        @Override
5930        public long getWifiScanActualTime(final long elapsedRealtimeUs) {
5931            if (mWifiScanTimer == null) {
5932                return 0;
5933            }
5934            final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
5935            return mWifiScanTimer.getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
5936        }
5937
5938        @Override
5939        public long getWifiScanBackgroundTime(final long elapsedRealtimeUs) {
5940            if (mWifiScanTimer == null || mWifiScanTimer.getSubTimer() == null) {
5941                return 0;
5942            }
5943            final long elapsedRealtimeMs = (elapsedRealtimeUs + 500) / 1000;
5944            return mWifiScanTimer.getSubTimer().getTotalDurationMsLocked(elapsedRealtimeMs) * 1000;
5945        }
5946
5947        @Override
5948        public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
5949            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
5950            if (mWifiBatchedScanTimer[csphBin] == null) {
5951                return 0;
5952            }
5953            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
5954        }
5955
5956        @Override
5957        public int getWifiBatchedScanCount(int csphBin, int which) {
5958            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
5959            if (mWifiBatchedScanTimer[csphBin] == null) {
5960                return 0;
5961            }
5962            return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
5963        }
5964
5965        @Override
5966        public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
5967            if (mWifiMulticastTimer == null) {
5968                return 0;
5969            }
5970            return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5971        }
5972
5973        @Override
5974        public Timer getAudioTurnedOnTimer() {
5975            return mAudioTurnedOnTimer;
5976        }
5977
5978        @Override
5979        public Timer getVideoTurnedOnTimer() {
5980            return mVideoTurnedOnTimer;
5981        }
5982
5983        @Override
5984        public Timer getFlashlightTurnedOnTimer() {
5985            return mFlashlightTurnedOnTimer;
5986        }
5987
5988        @Override
5989        public Timer getCameraTurnedOnTimer() {
5990            return mCameraTurnedOnTimer;
5991        }
5992
5993        @Override
5994        public Timer getForegroundActivityTimer() {
5995            return mForegroundActivityTimer;
5996        }
5997
5998        @Override
5999        public Timer getBluetoothScanTimer() {
6000            return mBluetoothScanTimer;
6001        }
6002
6003        @Override
6004        public Timer getBluetoothScanBackgroundTimer() {
6005            if (mBluetoothScanTimer == null) {
6006                return null;
6007            }
6008            return mBluetoothScanTimer.getSubTimer();
6009        }
6010
6011        void makeProcessState(int i, Parcel in) {
6012            if (i < 0 || i >= NUM_PROCESS_STATE) return;
6013
6014            if (in == null) {
6015                mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
6016                        mBsi.mOnBatteryTimeBase);
6017            } else {
6018                mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
6019                        mBsi.mOnBatteryTimeBase, in);
6020            }
6021        }
6022
6023        @Override
6024        public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
6025            if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
6026            if (mProcessStateTimer[state] == null) {
6027                return 0;
6028            }
6029            return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
6030        }
6031
6032        @Override
6033        public Timer getProcessStateTimer(int state) {
6034            if (state < 0 || state >= NUM_PROCESS_STATE) return null;
6035            return mProcessStateTimer[state];
6036        }
6037
6038        @Override
6039        public Timer getVibratorOnTimer() {
6040            return mVibratorOnTimer;
6041        }
6042
6043        @Override
6044        public void noteUserActivityLocked(int type) {
6045            if (mUserActivityCounters == null) {
6046                initUserActivityLocked();
6047            }
6048            if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
6049                mUserActivityCounters[type].stepAtomic();
6050            } else {
6051                Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
6052                        new Throwable());
6053            }
6054        }
6055
6056        @Override
6057        public boolean hasUserActivity() {
6058            return mUserActivityCounters != null;
6059        }
6060
6061        @Override
6062        public int getUserActivityCount(int type, int which) {
6063            if (mUserActivityCounters == null) {
6064                return 0;
6065            }
6066            return mUserActivityCounters[type].getCountLocked(which);
6067        }
6068
6069        void makeWifiBatchedScanBin(int i, Parcel in) {
6070            if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
6071
6072            ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
6073            if (collected == null) {
6074                collected = new ArrayList<StopwatchTimer>();
6075                mBsi.mWifiBatchedScanTimers.put(i, collected);
6076            }
6077            if (in == null) {
6078                mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
6079                        collected, mBsi.mOnBatteryTimeBase);
6080            } else {
6081                mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
6082                        collected, mBsi.mOnBatteryTimeBase, in);
6083            }
6084        }
6085
6086
6087        void initUserActivityLocked() {
6088            mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
6089            for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6090                mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
6091            }
6092        }
6093
6094        void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
6095            if (mNetworkByteActivityCounters == null) {
6096                initNetworkActivityLocked();
6097            }
6098            if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
6099                mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
6100                mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
6101            } else {
6102                Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
6103                        new Throwable());
6104            }
6105        }
6106
6107        void noteMobileRadioActiveTimeLocked(long batteryUptime) {
6108            if (mNetworkByteActivityCounters == null) {
6109                initNetworkActivityLocked();
6110            }
6111            mMobileRadioActiveTime.addCountLocked(batteryUptime);
6112            mMobileRadioActiveCount.addCountLocked(1);
6113        }
6114
6115        @Override
6116        public boolean hasNetworkActivity() {
6117            return mNetworkByteActivityCounters != null;
6118        }
6119
6120        @Override
6121        public long getNetworkActivityBytes(int type, int which) {
6122            if (mNetworkByteActivityCounters != null && type >= 0
6123                    && type < mNetworkByteActivityCounters.length) {
6124                return mNetworkByteActivityCounters[type].getCountLocked(which);
6125            } else {
6126                return 0;
6127            }
6128        }
6129
6130        @Override
6131        public long getNetworkActivityPackets(int type, int which) {
6132            if (mNetworkPacketActivityCounters != null && type >= 0
6133                    && type < mNetworkPacketActivityCounters.length) {
6134                return mNetworkPacketActivityCounters[type].getCountLocked(which);
6135            } else {
6136                return 0;
6137            }
6138        }
6139
6140        @Override
6141        public long getMobileRadioActiveTime(int which) {
6142            return mMobileRadioActiveTime != null
6143                    ? mMobileRadioActiveTime.getCountLocked(which) : 0;
6144        }
6145
6146        @Override
6147        public int getMobileRadioActiveCount(int which) {
6148            return mMobileRadioActiveCount != null
6149                    ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
6150        }
6151
6152        @Override
6153        public long getUserCpuTimeUs(int which) {
6154            return mUserCpuTime.getCountLocked(which);
6155        }
6156
6157        @Override
6158        public long getSystemCpuTimeUs(int which) {
6159            return mSystemCpuTime.getCountLocked(which);
6160        }
6161
6162        @Override
6163        public long getTimeAtCpuSpeed(int cluster, int step, int which) {
6164            if (mCpuClusterSpeed != null) {
6165                if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
6166                    final LongSamplingCounter[] cpuSpeeds = mCpuClusterSpeed[cluster];
6167                    if (cpuSpeeds != null) {
6168                        if (step >= 0 && step < cpuSpeeds.length) {
6169                            final LongSamplingCounter c = cpuSpeeds[step];
6170                            if (c != null) {
6171                                return c.getCountLocked(which);
6172                            }
6173                        }
6174                    }
6175                }
6176            }
6177            return 0;
6178        }
6179
6180        public void noteMobileRadioApWakeupLocked() {
6181            if (mMobileRadioApWakeupCount == null) {
6182                mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6183            }
6184            mMobileRadioApWakeupCount.addCountLocked(1);
6185        }
6186
6187        @Override
6188        public long getMobileRadioApWakeupCount(int which) {
6189            if (mMobileRadioApWakeupCount != null) {
6190                return mMobileRadioApWakeupCount.getCountLocked(which);
6191            }
6192            return 0;
6193        }
6194
6195        public void noteWifiRadioApWakeupLocked() {
6196            if (mWifiRadioApWakeupCount == null) {
6197                mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6198            }
6199            mWifiRadioApWakeupCount.addCountLocked(1);
6200        }
6201
6202        @Override
6203        public long getWifiRadioApWakeupCount(int which) {
6204            if (mWifiRadioApWakeupCount != null) {
6205                return mWifiRadioApWakeupCount.getCountLocked(which);
6206            }
6207            return 0;
6208        }
6209
6210        void initNetworkActivityLocked() {
6211            mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6212            mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6213            for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6214                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6215                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6216            }
6217            mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6218            mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
6219        }
6220
6221        /**
6222         * Clear all stats for this uid.  Returns true if the uid is completely
6223         * inactive so can be dropped.
6224         */
6225        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
6226        public boolean reset() {
6227            boolean active = false;
6228
6229            if (mWifiRunningTimer != null) {
6230                active |= !mWifiRunningTimer.reset(false);
6231                active |= mWifiRunning;
6232            }
6233            if (mFullWifiLockTimer != null) {
6234                active |= !mFullWifiLockTimer.reset(false);
6235                active |= mFullWifiLockOut;
6236            }
6237            if (mWifiScanTimer != null) {
6238                active |= !mWifiScanTimer.reset(false);
6239                active |= mWifiScanStarted;
6240            }
6241            if (mWifiBatchedScanTimer != null) {
6242                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
6243                    if (mWifiBatchedScanTimer[i] != null) {
6244                        active |= !mWifiBatchedScanTimer[i].reset(false);
6245                    }
6246                }
6247                active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
6248            }
6249            if (mWifiMulticastTimer != null) {
6250                active |= !mWifiMulticastTimer.reset(false);
6251                active |= mWifiMulticastEnabled;
6252            }
6253
6254            active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
6255            active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
6256            active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
6257            active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
6258            active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
6259            active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
6260
6261            if (mProcessStateTimer != null) {
6262                for (int i = 0; i < NUM_PROCESS_STATE; i++) {
6263                    if (mProcessStateTimer[i] != null) {
6264                        active |= !mProcessStateTimer[i].reset(false);
6265                    }
6266                }
6267                active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
6268            }
6269            if (mVibratorOnTimer != null) {
6270                if (mVibratorOnTimer.reset(false)) {
6271                    mVibratorOnTimer.detach();
6272                    mVibratorOnTimer = null;
6273                } else {
6274                    active = true;
6275                }
6276            }
6277
6278            if (mUserActivityCounters != null) {
6279                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6280                    mUserActivityCounters[i].reset(false);
6281                }
6282            }
6283
6284            if (mNetworkByteActivityCounters != null) {
6285                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6286                    mNetworkByteActivityCounters[i].reset(false);
6287                    mNetworkPacketActivityCounters[i].reset(false);
6288                }
6289                mMobileRadioActiveTime.reset(false);
6290                mMobileRadioActiveCount.reset(false);
6291            }
6292
6293            if (mWifiControllerActivity != null) {
6294                mWifiControllerActivity.reset(false);
6295            }
6296
6297            if (mBluetoothControllerActivity != null) {
6298                mBluetoothControllerActivity.reset(false);
6299            }
6300
6301            if (mModemControllerActivity != null) {
6302                mModemControllerActivity.reset(false);
6303            }
6304
6305            mUserCpuTime.reset(false);
6306            mSystemCpuTime.reset(false);
6307
6308            if (mCpuClusterSpeed != null) {
6309                for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
6310                    if (speeds != null) {
6311                        for (LongSamplingCounter speed : speeds) {
6312                            if (speed != null) {
6313                                speed.reset(false);
6314                            }
6315                        }
6316                    }
6317                }
6318            }
6319
6320            resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
6321            resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
6322
6323            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
6324            for (int iw=wakeStats.size()-1; iw>=0; iw--) {
6325                Wakelock wl = wakeStats.valueAt(iw);
6326                if (wl.reset()) {
6327                    wakeStats.removeAt(iw);
6328                } else {
6329                    active = true;
6330                }
6331            }
6332            mWakelockStats.cleanup();
6333            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
6334            for (int is=syncStats.size()-1; is>=0; is--) {
6335                StopwatchTimer timer = syncStats.valueAt(is);
6336                if (timer.reset(false)) {
6337                    syncStats.removeAt(is);
6338                    timer.detach();
6339                } else {
6340                    active = true;
6341                }
6342            }
6343            mSyncStats.cleanup();
6344            final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
6345            for (int ij=jobStats.size()-1; ij>=0; ij--) {
6346                DualTimer timer = jobStats.valueAt(ij);
6347                if (timer.reset(false)) {
6348                    jobStats.removeAt(ij);
6349                    timer.detach();
6350                } else {
6351                    active = true;
6352                }
6353            }
6354            mJobStats.cleanup();
6355            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
6356                Sensor s = mSensorStats.valueAt(ise);
6357                if (s.reset()) {
6358                    mSensorStats.removeAt(ise);
6359                } else {
6360                    active = true;
6361                }
6362            }
6363            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
6364                Proc proc = mProcessStats.valueAt(ip);
6365                proc.detach();
6366            }
6367            mProcessStats.clear();
6368            if (mPids.size() > 0) {
6369                for (int i=mPids.size()-1; i>=0; i--) {
6370                    Pid pid = mPids.valueAt(i);
6371                    if (pid.mWakeNesting > 0) {
6372                        active = true;
6373                    } else {
6374                        mPids.removeAt(i);
6375                    }
6376                }
6377            }
6378            if (mPackageStats.size() > 0) {
6379                Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
6380                while (it.hasNext()) {
6381                    Map.Entry<String, Pkg> pkgEntry = it.next();
6382                    Pkg p = pkgEntry.getValue();
6383                    p.detach();
6384                    if (p.mServiceStats.size() > 0) {
6385                        Iterator<Map.Entry<String, Pkg.Serv>> it2
6386                                = p.mServiceStats.entrySet().iterator();
6387                        while (it2.hasNext()) {
6388                            Map.Entry<String, Pkg.Serv> servEntry = it2.next();
6389                            servEntry.getValue().detach();
6390                        }
6391                    }
6392                }
6393                mPackageStats.clear();
6394            }
6395
6396            mLastStepUserTime = mLastStepSystemTime = 0;
6397            mCurStepUserTime = mCurStepSystemTime = 0;
6398
6399            mOnBatteryBackgroundTimeBase.reset(mBsi.mClocks.elapsedRealtime() * 1000,
6400                    mBsi.mClocks.uptimeMillis() * 1000);
6401
6402            if (!active) {
6403                if (mWifiRunningTimer != null) {
6404                    mWifiRunningTimer.detach();
6405                }
6406                if (mFullWifiLockTimer != null) {
6407                    mFullWifiLockTimer.detach();
6408                }
6409                if (mWifiScanTimer != null) {
6410                    mWifiScanTimer.detach();
6411                }
6412                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
6413                    if (mWifiBatchedScanTimer[i] != null) {
6414                        mWifiBatchedScanTimer[i].detach();
6415                    }
6416                }
6417                if (mWifiMulticastTimer != null) {
6418                    mWifiMulticastTimer.detach();
6419                }
6420                if (mAudioTurnedOnTimer != null) {
6421                    mAudioTurnedOnTimer.detach();
6422                    mAudioTurnedOnTimer = null;
6423                }
6424                if (mVideoTurnedOnTimer != null) {
6425                    mVideoTurnedOnTimer.detach();
6426                    mVideoTurnedOnTimer = null;
6427                }
6428                if (mFlashlightTurnedOnTimer != null) {
6429                    mFlashlightTurnedOnTimer.detach();
6430                    mFlashlightTurnedOnTimer = null;
6431                }
6432                if (mCameraTurnedOnTimer != null) {
6433                    mCameraTurnedOnTimer.detach();
6434                    mCameraTurnedOnTimer = null;
6435                }
6436                if (mForegroundActivityTimer != null) {
6437                    mForegroundActivityTimer.detach();
6438                    mForegroundActivityTimer = null;
6439                }
6440                if (mBluetoothScanTimer != null) {
6441                    mBluetoothScanTimer.detach();
6442                    mBluetoothScanTimer = null;
6443                }
6444                if (mUserActivityCounters != null) {
6445                    for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6446                        mUserActivityCounters[i].detach();
6447                    }
6448                }
6449                if (mNetworkByteActivityCounters != null) {
6450                    for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6451                        mNetworkByteActivityCounters[i].detach();
6452                        mNetworkPacketActivityCounters[i].detach();
6453                    }
6454                }
6455
6456                if (mWifiControllerActivity != null) {
6457                    mWifiControllerActivity.detach();
6458                }
6459
6460                if (mBluetoothControllerActivity != null) {
6461                    mBluetoothControllerActivity.detach();
6462                }
6463
6464                if (mModemControllerActivity != null) {
6465                    mModemControllerActivity.detach();
6466                }
6467
6468                mPids.clear();
6469
6470                mUserCpuTime.detach();
6471                mSystemCpuTime.detach();
6472
6473                if (mCpuClusterSpeed != null) {
6474                    for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
6475                        if (cpuSpeeds != null) {
6476                            for (LongSamplingCounter c : cpuSpeeds) {
6477                                if (c != null) {
6478                                    c.detach();
6479                                }
6480                            }
6481                        }
6482                    }
6483                }
6484
6485                detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
6486                detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
6487            }
6488
6489            return !active;
6490        }
6491
6492        void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
6493            mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
6494
6495            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
6496            int NW = wakeStats.size();
6497            out.writeInt(NW);
6498            for (int iw=0; iw<NW; iw++) {
6499                out.writeString(wakeStats.keyAt(iw));
6500                Uid.Wakelock wakelock = wakeStats.valueAt(iw);
6501                wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
6502            }
6503
6504            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
6505            int NS = syncStats.size();
6506            out.writeInt(NS);
6507            for (int is=0; is<NS; is++) {
6508                out.writeString(syncStats.keyAt(is));
6509                StopwatchTimer timer = syncStats.valueAt(is);
6510                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
6511            }
6512
6513            final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
6514            int NJ = jobStats.size();
6515            out.writeInt(NJ);
6516            for (int ij=0; ij<NJ; ij++) {
6517                out.writeString(jobStats.keyAt(ij));
6518                DualTimer timer = jobStats.valueAt(ij);
6519                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
6520            }
6521
6522            int NSE = mSensorStats.size();
6523            out.writeInt(NSE);
6524            for (int ise=0; ise<NSE; ise++) {
6525                out.writeInt(mSensorStats.keyAt(ise));
6526                Uid.Sensor sensor = mSensorStats.valueAt(ise);
6527                sensor.writeToParcelLocked(out, elapsedRealtimeUs);
6528            }
6529
6530            int NP = mProcessStats.size();
6531            out.writeInt(NP);
6532            for (int ip=0; ip<NP; ip++) {
6533                out.writeString(mProcessStats.keyAt(ip));
6534                Uid.Proc proc = mProcessStats.valueAt(ip);
6535                proc.writeToParcelLocked(out);
6536            }
6537
6538            out.writeInt(mPackageStats.size());
6539            for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
6540                out.writeString(pkgEntry.getKey());
6541                Uid.Pkg pkg = pkgEntry.getValue();
6542                pkg.writeToParcelLocked(out);
6543            }
6544
6545            if (mWifiRunningTimer != null) {
6546                out.writeInt(1);
6547                mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
6548            } else {
6549                out.writeInt(0);
6550            }
6551            if (mFullWifiLockTimer != null) {
6552                out.writeInt(1);
6553                mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
6554            } else {
6555                out.writeInt(0);
6556            }
6557            if (mWifiScanTimer != null) {
6558                out.writeInt(1);
6559                mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
6560            } else {
6561                out.writeInt(0);
6562            }
6563            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
6564                if (mWifiBatchedScanTimer[i] != null) {
6565                    out.writeInt(1);
6566                    mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
6567                } else {
6568                    out.writeInt(0);
6569                }
6570            }
6571            if (mWifiMulticastTimer != null) {
6572                out.writeInt(1);
6573                mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
6574            } else {
6575                out.writeInt(0);
6576            }
6577
6578            if (mAudioTurnedOnTimer != null) {
6579                out.writeInt(1);
6580                mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6581            } else {
6582                out.writeInt(0);
6583            }
6584            if (mVideoTurnedOnTimer != null) {
6585                out.writeInt(1);
6586                mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6587            } else {
6588                out.writeInt(0);
6589            }
6590            if (mFlashlightTurnedOnTimer != null) {
6591                out.writeInt(1);
6592                mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6593            } else {
6594                out.writeInt(0);
6595            }
6596            if (mCameraTurnedOnTimer != null) {
6597                out.writeInt(1);
6598                mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6599            } else {
6600                out.writeInt(0);
6601            }
6602            if (mForegroundActivityTimer != null) {
6603                out.writeInt(1);
6604                mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
6605            } else {
6606                out.writeInt(0);
6607            }
6608            if (mBluetoothScanTimer != null) {
6609                out.writeInt(1);
6610                mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
6611            } else {
6612                out.writeInt(0);
6613            }
6614            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
6615                if (mProcessStateTimer[i] != null) {
6616                    out.writeInt(1);
6617                    mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
6618                } else {
6619                    out.writeInt(0);
6620                }
6621            }
6622            if (mVibratorOnTimer != null) {
6623                out.writeInt(1);
6624                mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
6625            } else {
6626                out.writeInt(0);
6627            }
6628            if (mUserActivityCounters != null) {
6629                out.writeInt(1);
6630                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6631                    mUserActivityCounters[i].writeToParcel(out);
6632                }
6633            } else {
6634                out.writeInt(0);
6635            }
6636            if (mNetworkByteActivityCounters != null) {
6637                out.writeInt(1);
6638                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6639                    mNetworkByteActivityCounters[i].writeToParcel(out);
6640                    mNetworkPacketActivityCounters[i].writeToParcel(out);
6641                }
6642                mMobileRadioActiveTime.writeToParcel(out);
6643                mMobileRadioActiveCount.writeToParcel(out);
6644            } else {
6645                out.writeInt(0);
6646            }
6647
6648            if (mWifiControllerActivity != null) {
6649                out.writeInt(1);
6650                mWifiControllerActivity.writeToParcel(out, 0);
6651            } else {
6652                out.writeInt(0);
6653            }
6654
6655            if (mBluetoothControllerActivity != null) {
6656                out.writeInt(1);
6657                mBluetoothControllerActivity.writeToParcel(out, 0);
6658            } else {
6659                out.writeInt(0);
6660            }
6661
6662            if (mModemControllerActivity != null) {
6663                out.writeInt(1);
6664                mModemControllerActivity.writeToParcel(out, 0);
6665            } else {
6666                out.writeInt(0);
6667            }
6668
6669            mUserCpuTime.writeToParcel(out);
6670            mSystemCpuTime.writeToParcel(out);
6671
6672            if (mCpuClusterSpeed != null) {
6673                out.writeInt(1);
6674                out.writeInt(mCpuClusterSpeed.length);
6675                for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
6676                    if (cpuSpeeds != null) {
6677                        out.writeInt(1);
6678                        out.writeInt(cpuSpeeds.length);
6679                        for (LongSamplingCounter c : cpuSpeeds) {
6680                            if (c != null) {
6681                                out.writeInt(1);
6682                                c.writeToParcel(out);
6683                            } else {
6684                                out.writeInt(0);
6685                            }
6686                        }
6687                    } else {
6688                        out.writeInt(0);
6689                    }
6690                }
6691            } else {
6692                out.writeInt(0);
6693            }
6694
6695            if (mMobileRadioApWakeupCount != null) {
6696                out.writeInt(1);
6697                mMobileRadioApWakeupCount.writeToParcel(out);
6698            } else {
6699                out.writeInt(0);
6700            }
6701
6702            if (mWifiRadioApWakeupCount != null) {
6703                out.writeInt(1);
6704                mWifiRadioApWakeupCount.writeToParcel(out);
6705            } else {
6706                out.writeInt(0);
6707            }
6708        }
6709
6710        void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
6711            mOnBatteryBackgroundTimeBase.readFromParcel(in);
6712
6713            int numWakelocks = in.readInt();
6714            mWakelockStats.clear();
6715            for (int j = 0; j < numWakelocks; j++) {
6716                String wakelockName = in.readString();
6717                Uid.Wakelock wakelock = new Wakelock(mBsi, this);
6718                wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
6719                mWakelockStats.add(wakelockName, wakelock);
6720            }
6721
6722            int numSyncs = in.readInt();
6723            mSyncStats.clear();
6724            for (int j = 0; j < numSyncs; j++) {
6725                String syncName = in.readString();
6726                if (in.readInt() != 0) {
6727                    mSyncStats.add(syncName,
6728                            new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null, timeBase, in));
6729                }
6730            }
6731
6732            int numJobs = in.readInt();
6733            mJobStats.clear();
6734            for (int j = 0; j < numJobs; j++) {
6735                String jobName = in.readString();
6736                if (in.readInt() != 0) {
6737                    mJobStats.add(jobName, new DualTimer(mBsi.mClocks, Uid.this, JOB, null,
6738                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
6739                }
6740            }
6741
6742            int numSensors = in.readInt();
6743            mSensorStats.clear();
6744            for (int k = 0; k < numSensors; k++) {
6745                int sensorNumber = in.readInt();
6746                Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
6747                sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
6748                        in);
6749                mSensorStats.put(sensorNumber, sensor);
6750            }
6751
6752            int numProcs = in.readInt();
6753            mProcessStats.clear();
6754            for (int k = 0; k < numProcs; k++) {
6755                String processName = in.readString();
6756                Uid.Proc proc = new Proc(mBsi, processName);
6757                proc.readFromParcelLocked(in);
6758                mProcessStats.put(processName, proc);
6759            }
6760
6761            int numPkgs = in.readInt();
6762            mPackageStats.clear();
6763            for (int l = 0; l < numPkgs; l++) {
6764                String packageName = in.readString();
6765                Uid.Pkg pkg = new Pkg(mBsi);
6766                pkg.readFromParcelLocked(in);
6767                mPackageStats.put(packageName, pkg);
6768            }
6769
6770            mWifiRunning = false;
6771            if (in.readInt() != 0) {
6772                mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
6773                        mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
6774            } else {
6775                mWifiRunningTimer = null;
6776            }
6777            mFullWifiLockOut = false;
6778            if (in.readInt() != 0) {
6779                mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
6780                        mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
6781            } else {
6782                mFullWifiLockTimer = null;
6783            }
6784            mWifiScanStarted = false;
6785            if (in.readInt() != 0) {
6786                mWifiScanTimer = new DualTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
6787                        mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase,
6788                        in);
6789            } else {
6790                mWifiScanTimer = null;
6791            }
6792            mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6793            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
6794                if (in.readInt() != 0) {
6795                    makeWifiBatchedScanBin(i, in);
6796                } else {
6797                    mWifiBatchedScanTimer[i] = null;
6798                }
6799            }
6800            mWifiMulticastEnabled = false;
6801            if (in.readInt() != 0) {
6802                mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
6803                        mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
6804            } else {
6805                mWifiMulticastTimer = null;
6806            }
6807            if (in.readInt() != 0) {
6808                mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
6809                        mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6810            } else {
6811                mAudioTurnedOnTimer = null;
6812            }
6813            if (in.readInt() != 0) {
6814                mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
6815                        mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6816            } else {
6817                mVideoTurnedOnTimer = null;
6818            }
6819            if (in.readInt() != 0) {
6820                mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6821                        FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6822            } else {
6823                mFlashlightTurnedOnTimer = null;
6824            }
6825            if (in.readInt() != 0) {
6826                mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
6827                        mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6828            } else {
6829                mCameraTurnedOnTimer = null;
6830            }
6831            if (in.readInt() != 0) {
6832                mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6833                        FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
6834            } else {
6835                mForegroundActivityTimer = null;
6836            }
6837            if (in.readInt() != 0) {
6838                mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
6839                        mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
6840                        mOnBatteryBackgroundTimeBase, in);
6841            } else {
6842                mBluetoothScanTimer = null;
6843            }
6844            mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6845            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
6846                if (in.readInt() != 0) {
6847                    makeProcessState(i, in);
6848                } else {
6849                    mProcessStateTimer[i] = null;
6850                }
6851            }
6852            if (in.readInt() != 0) {
6853                mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
6854                        mBsi.mOnBatteryTimeBase, in);
6855            } else {
6856                mVibratorOnTimer = null;
6857            }
6858            if (in.readInt() != 0) {
6859                mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
6860                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6861                    mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
6862                }
6863            } else {
6864                mUserActivityCounters = null;
6865            }
6866            if (in.readInt() != 0) {
6867                mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6868                mNetworkPacketActivityCounters
6869                        = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6870                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6871                    mNetworkByteActivityCounters[i]
6872                            = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6873                    mNetworkPacketActivityCounters[i]
6874                            = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6875                }
6876                mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6877                mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6878            } else {
6879                mNetworkByteActivityCounters = null;
6880                mNetworkPacketActivityCounters = null;
6881            }
6882
6883            if (in.readInt() != 0) {
6884                mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6885                        NUM_WIFI_TX_LEVELS, in);
6886            } else {
6887                mWifiControllerActivity = null;
6888            }
6889
6890            if (in.readInt() != 0) {
6891                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6892                        NUM_BT_TX_LEVELS, in);
6893            } else {
6894                mBluetoothControllerActivity = null;
6895            }
6896
6897            if (in.readInt() != 0) {
6898                mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6899                        ModemActivityInfo.TX_POWER_LEVELS, in);
6900            } else {
6901                mModemControllerActivity = null;
6902            }
6903
6904            mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6905            mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6906
6907            if (in.readInt() != 0) {
6908                int numCpuClusters = in.readInt();
6909                if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
6910                    throw new ParcelFormatException("Incompatible number of cpu clusters");
6911                }
6912
6913                mCpuClusterSpeed = new LongSamplingCounter[numCpuClusters][];
6914                for (int cluster = 0; cluster < numCpuClusters; cluster++) {
6915                    if (in.readInt() != 0) {
6916                        int numSpeeds = in.readInt();
6917                        if (mBsi.mPowerProfile != null &&
6918                                mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
6919                            throw new ParcelFormatException("Incompatible number of cpu speeds");
6920                        }
6921
6922                        final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
6923                        mCpuClusterSpeed[cluster] = cpuSpeeds;
6924                        for (int speed = 0; speed < numSpeeds; speed++) {
6925                            if (in.readInt() != 0) {
6926                                cpuSpeeds[speed] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6927                            }
6928                        }
6929                    } else {
6930                        mCpuClusterSpeed[cluster] = null;
6931                    }
6932                }
6933            } else {
6934                mCpuClusterSpeed = null;
6935            }
6936
6937            if (in.readInt() != 0) {
6938                mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6939            } else {
6940                mMobileRadioApWakeupCount = null;
6941            }
6942
6943            if (in.readInt() != 0) {
6944                mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6945            } else {
6946                mWifiRadioApWakeupCount = null;
6947            }
6948        }
6949
6950        /**
6951         * The statistics associated with a particular wake lock.
6952         */
6953        public static class Wakelock extends BatteryStats.Uid.Wakelock {
6954            /**
6955             * BatteryStatsImpl that we are associated with.
6956             */
6957            protected BatteryStatsImpl mBsi;
6958
6959            /**
6960             * BatteryStatsImpl that we are associated with.
6961             */
6962            protected Uid mUid;
6963
6964            /**
6965             * How long (in ms) this uid has been keeping the device partially awake.
6966             */
6967            DurationTimer mTimerPartial;
6968
6969            /**
6970             * How long (in ms) this uid has been keeping the device fully awake.
6971             */
6972            StopwatchTimer mTimerFull;
6973
6974            /**
6975             * How long (in ms) this uid has had a window keeping the device awake.
6976             */
6977            StopwatchTimer mTimerWindow;
6978
6979            /**
6980             * How long (in ms) this uid has had a draw wake lock.
6981             */
6982            StopwatchTimer mTimerDraw;
6983
6984            public Wakelock(BatteryStatsImpl bsi, Uid uid) {
6985                mBsi = bsi;
6986                mUid = uid;
6987            }
6988
6989            /**
6990             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
6991             * proper timer pool from the given BatteryStatsImpl object.
6992             *
6993             * @param in the Parcel to be read from.
6994             * return a new Timer, or null.
6995             */
6996            private StopwatchTimer readStopwatchTimerFromParcel(int type,
6997                    ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
6998                if (in.readInt() == 0) {
6999                    return null;
7000                }
7001
7002                return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
7003            }
7004
7005            /**
7006             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
7007             * proper timer pool from the given BatteryStatsImpl object.
7008             *
7009             * @param in the Parcel to be read from.
7010             * return a new Timer, or null.
7011             */
7012            private DurationTimer readDurationTimerFromParcel(int type,
7013                    ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
7014                if (in.readInt() == 0) {
7015                    return null;
7016                }
7017
7018                return new DurationTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
7019            }
7020
7021            boolean reset() {
7022                boolean wlactive = false;
7023                if (mTimerFull != null) {
7024                    wlactive |= !mTimerFull.reset(false);
7025                }
7026                if (mTimerPartial != null) {
7027                    wlactive |= !mTimerPartial.reset(false);
7028                }
7029                if (mTimerWindow != null) {
7030                    wlactive |= !mTimerWindow.reset(false);
7031                }
7032                if (mTimerDraw != null) {
7033                    wlactive |= !mTimerDraw.reset(false);
7034                }
7035                if (!wlactive) {
7036                    if (mTimerFull != null) {
7037                        mTimerFull.detach();
7038                        mTimerFull = null;
7039                    }
7040                    if (mTimerPartial != null) {
7041                        mTimerPartial.detach();
7042                        mTimerPartial = null;
7043                    }
7044                    if (mTimerWindow != null) {
7045                        mTimerWindow.detach();
7046                        mTimerWindow = null;
7047                    }
7048                    if (mTimerDraw != null) {
7049                        mTimerDraw.detach();
7050                        mTimerDraw = null;
7051                    }
7052                }
7053                return !wlactive;
7054            }
7055
7056            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
7057                mTimerPartial = readDurationTimerFromParcel(WAKE_TYPE_PARTIAL,
7058                        mBsi.mPartialTimers, screenOffTimeBase, in);
7059                mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
7060                        mBsi.mFullTimers, timeBase, in);
7061                mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
7062                        mBsi.mWindowTimers, timeBase, in);
7063                mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
7064                        mBsi.mDrawTimers, timeBase, in);
7065            }
7066
7067            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
7068                Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
7069                Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
7070                Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
7071                Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
7072            }
7073
7074            @Override
7075            public Timer getWakeTime(int type) {
7076                switch (type) {
7077                case WAKE_TYPE_FULL: return mTimerFull;
7078                case WAKE_TYPE_PARTIAL: return mTimerPartial;
7079                case WAKE_TYPE_WINDOW: return mTimerWindow;
7080                case WAKE_TYPE_DRAW: return mTimerDraw;
7081                default: throw new IllegalArgumentException("type = " + type);
7082                }
7083            }
7084
7085            public StopwatchTimer getStopwatchTimer(int type) {
7086                switch (type) {
7087                    case WAKE_TYPE_PARTIAL: {
7088                        DurationTimer t = mTimerPartial;
7089                        if (t == null) {
7090                            t = new DurationTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL,
7091                                    mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase);
7092                            mTimerPartial = t;
7093                        }
7094                        return t;
7095                    }
7096                    case WAKE_TYPE_FULL: {
7097                        StopwatchTimer t = mTimerFull;
7098                        if (t == null) {
7099                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL,
7100                                    mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
7101                            mTimerFull = t;
7102                        }
7103                        return t;
7104                    }
7105                    case WAKE_TYPE_WINDOW: {
7106                        StopwatchTimer t = mTimerWindow;
7107                        if (t == null) {
7108                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW,
7109                                    mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
7110                            mTimerWindow = t;
7111                        }
7112                        return t;
7113                    }
7114                    case WAKE_TYPE_DRAW: {
7115                        StopwatchTimer t = mTimerDraw;
7116                        if (t == null) {
7117                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW,
7118                                    mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
7119                            mTimerDraw = t;
7120                        }
7121                        return t;
7122                    }
7123                    default:
7124                        throw new IllegalArgumentException("type=" + type);
7125                }
7126            }
7127        }
7128
7129        public static class Sensor extends BatteryStats.Uid.Sensor {
7130            /**
7131             * BatteryStatsImpl that we are associated with.
7132             */
7133            protected BatteryStatsImpl mBsi;
7134
7135            /**
7136             * Uid that we are associated with.
7137             */
7138            protected Uid mUid;
7139
7140            final int mHandle;
7141            DualTimer mTimer;
7142
7143            public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
7144                mBsi = bsi;
7145                mUid = uid;
7146                mHandle = handle;
7147            }
7148
7149            private DualTimer readTimersFromParcel(
7150                    TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
7151                if (in.readInt() == 0) {
7152                    return null;
7153                }
7154
7155                ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
7156                if (pool == null) {
7157                    pool = new ArrayList<StopwatchTimer>();
7158                    mBsi.mSensorTimers.put(mHandle, pool);
7159                }
7160                return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in);
7161            }
7162
7163            boolean reset() {
7164                if (mTimer.reset(true)) {
7165                    mTimer = null;
7166                    return true;
7167                }
7168                return false;
7169            }
7170
7171            void readFromParcelLocked(TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
7172                mTimer = readTimersFromParcel(timeBase, bgTimeBase, in);
7173            }
7174
7175            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
7176                Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
7177            }
7178
7179            @Override
7180            public Timer getSensorTime() {
7181                return mTimer;
7182            }
7183
7184            @Override
7185            public Timer getSensorBackgroundTime() {
7186                if (mTimer == null) {
7187                    return null;
7188                }
7189                return mTimer.getSubTimer();
7190            }
7191
7192            @Override
7193            public int getHandle() {
7194                return mHandle;
7195            }
7196        }
7197
7198        /**
7199         * The statistics associated with a particular process.
7200         */
7201        public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
7202            /**
7203             * BatteryStatsImpl that we are associated with.
7204             */
7205            protected BatteryStatsImpl mBsi;
7206
7207            /**
7208             * The name of this process.
7209             */
7210            final String mName;
7211
7212            /**
7213             * Remains true until removed from the stats.
7214             */
7215            boolean mActive = true;
7216
7217            /**
7218             * Total time (in ms) spent executing in user code.
7219             */
7220            long mUserTime;
7221
7222            /**
7223             * Total time (in ms) spent executing in kernel code.
7224             */
7225            long mSystemTime;
7226
7227            /**
7228             * Amount of time (in ms) the process was running in the foreground.
7229             */
7230            long mForegroundTime;
7231
7232            /**
7233             * Number of times the process has been started.
7234             */
7235            int mStarts;
7236
7237            /**
7238             * Number of times the process has crashed.
7239             */
7240            int mNumCrashes;
7241
7242            /**
7243             * Number of times the process has had an ANR.
7244             */
7245            int mNumAnrs;
7246
7247            /**
7248             * The amount of user time loaded from a previous save.
7249             */
7250            long mLoadedUserTime;
7251
7252            /**
7253             * The amount of system time loaded from a previous save.
7254             */
7255            long mLoadedSystemTime;
7256
7257            /**
7258             * The amount of foreground time loaded from a previous save.
7259             */
7260            long mLoadedForegroundTime;
7261
7262            /**
7263             * The number of times the process has started from a previous save.
7264             */
7265            int mLoadedStarts;
7266
7267            /**
7268             * Number of times the process has crashed from a previous save.
7269             */
7270            int mLoadedNumCrashes;
7271
7272            /**
7273             * Number of times the process has had an ANR from a previous save.
7274             */
7275            int mLoadedNumAnrs;
7276
7277            /**
7278             * The amount of user time when last unplugged.
7279             */
7280            long mUnpluggedUserTime;
7281
7282            /**
7283             * The amount of system time when last unplugged.
7284             */
7285            long mUnpluggedSystemTime;
7286
7287            /**
7288             * The amount of foreground time since unplugged.
7289             */
7290            long mUnpluggedForegroundTime;
7291
7292            /**
7293             * The number of times the process has started before unplugged.
7294             */
7295            int mUnpluggedStarts;
7296
7297            /**
7298             * Number of times the process has crashed before unplugged.
7299             */
7300            int mUnpluggedNumCrashes;
7301
7302            /**
7303             * Number of times the process has had an ANR before unplugged.
7304             */
7305            int mUnpluggedNumAnrs;
7306
7307            ArrayList<ExcessivePower> mExcessivePower;
7308
7309            public Proc(BatteryStatsImpl bsi, String name) {
7310                mBsi = bsi;
7311                mName = name;
7312                mBsi.mOnBatteryTimeBase.add(this);
7313            }
7314
7315            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
7316                mUnpluggedUserTime = mUserTime;
7317                mUnpluggedSystemTime = mSystemTime;
7318                mUnpluggedForegroundTime = mForegroundTime;
7319                mUnpluggedStarts = mStarts;
7320                mUnpluggedNumCrashes = mNumCrashes;
7321                mUnpluggedNumAnrs = mNumAnrs;
7322            }
7323
7324            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
7325            }
7326
7327            void detach() {
7328                mActive = false;
7329                mBsi.mOnBatteryTimeBase.remove(this);
7330            }
7331
7332            public int countExcessivePowers() {
7333                return mExcessivePower != null ? mExcessivePower.size() : 0;
7334            }
7335
7336            public ExcessivePower getExcessivePower(int i) {
7337                if (mExcessivePower != null) {
7338                    return mExcessivePower.get(i);
7339                }
7340                return null;
7341            }
7342
7343            public void addExcessiveWake(long overTime, long usedTime) {
7344                if (mExcessivePower == null) {
7345                    mExcessivePower = new ArrayList<ExcessivePower>();
7346                }
7347                ExcessivePower ew = new ExcessivePower();
7348                ew.type = ExcessivePower.TYPE_WAKE;
7349                ew.overTime = overTime;
7350                ew.usedTime = usedTime;
7351                mExcessivePower.add(ew);
7352            }
7353
7354            public void addExcessiveCpu(long overTime, long usedTime) {
7355                if (mExcessivePower == null) {
7356                    mExcessivePower = new ArrayList<ExcessivePower>();
7357                }
7358                ExcessivePower ew = new ExcessivePower();
7359                ew.type = ExcessivePower.TYPE_CPU;
7360                ew.overTime = overTime;
7361                ew.usedTime = usedTime;
7362                mExcessivePower.add(ew);
7363            }
7364
7365            void writeExcessivePowerToParcelLocked(Parcel out) {
7366                if (mExcessivePower == null) {
7367                    out.writeInt(0);
7368                    return;
7369                }
7370
7371                final int N = mExcessivePower.size();
7372                out.writeInt(N);
7373                for (int i=0; i<N; i++) {
7374                    ExcessivePower ew = mExcessivePower.get(i);
7375                    out.writeInt(ew.type);
7376                    out.writeLong(ew.overTime);
7377                    out.writeLong(ew.usedTime);
7378                }
7379            }
7380
7381            void readExcessivePowerFromParcelLocked(Parcel in) {
7382                final int N = in.readInt();
7383                if (N == 0) {
7384                    mExcessivePower = null;
7385                    return;
7386                }
7387
7388                if (N > 10000) {
7389                    throw new ParcelFormatException(
7390                            "File corrupt: too many excessive power entries " + N);
7391                }
7392
7393                mExcessivePower = new ArrayList<>();
7394                for (int i=0; i<N; i++) {
7395                    ExcessivePower ew = new ExcessivePower();
7396                    ew.type = in.readInt();
7397                    ew.overTime = in.readLong();
7398                    ew.usedTime = in.readLong();
7399                    mExcessivePower.add(ew);
7400                }
7401            }
7402
7403            void writeToParcelLocked(Parcel out) {
7404                out.writeLong(mUserTime);
7405                out.writeLong(mSystemTime);
7406                out.writeLong(mForegroundTime);
7407                out.writeInt(mStarts);
7408                out.writeInt(mNumCrashes);
7409                out.writeInt(mNumAnrs);
7410                out.writeLong(mLoadedUserTime);
7411                out.writeLong(mLoadedSystemTime);
7412                out.writeLong(mLoadedForegroundTime);
7413                out.writeInt(mLoadedStarts);
7414                out.writeInt(mLoadedNumCrashes);
7415                out.writeInt(mLoadedNumAnrs);
7416                out.writeLong(mUnpluggedUserTime);
7417                out.writeLong(mUnpluggedSystemTime);
7418                out.writeLong(mUnpluggedForegroundTime);
7419                out.writeInt(mUnpluggedStarts);
7420                out.writeInt(mUnpluggedNumCrashes);
7421                out.writeInt(mUnpluggedNumAnrs);
7422                writeExcessivePowerToParcelLocked(out);
7423            }
7424
7425            void readFromParcelLocked(Parcel in) {
7426                mUserTime = in.readLong();
7427                mSystemTime = in.readLong();
7428                mForegroundTime = in.readLong();
7429                mStarts = in.readInt();
7430                mNumCrashes = in.readInt();
7431                mNumAnrs = in.readInt();
7432                mLoadedUserTime = in.readLong();
7433                mLoadedSystemTime = in.readLong();
7434                mLoadedForegroundTime = in.readLong();
7435                mLoadedStarts = in.readInt();
7436                mLoadedNumCrashes = in.readInt();
7437                mLoadedNumAnrs = in.readInt();
7438                mUnpluggedUserTime = in.readLong();
7439                mUnpluggedSystemTime = in.readLong();
7440                mUnpluggedForegroundTime = in.readLong();
7441                mUnpluggedStarts = in.readInt();
7442                mUnpluggedNumCrashes = in.readInt();
7443                mUnpluggedNumAnrs = in.readInt();
7444                readExcessivePowerFromParcelLocked(in);
7445            }
7446
7447            public void addCpuTimeLocked(int utime, int stime) {
7448                mUserTime += utime;
7449                mSystemTime += stime;
7450            }
7451
7452            public void addForegroundTimeLocked(long ttime) {
7453                mForegroundTime += ttime;
7454            }
7455
7456            public void incStartsLocked() {
7457                mStarts++;
7458            }
7459
7460            public void incNumCrashesLocked() {
7461                mNumCrashes++;
7462            }
7463
7464            public void incNumAnrsLocked() {
7465                mNumAnrs++;
7466            }
7467
7468            @Override
7469            public boolean isActive() {
7470                return mActive;
7471            }
7472
7473            @Override
7474            public long getUserTime(int which) {
7475                long val = mUserTime;
7476                if (which == STATS_CURRENT) {
7477                    val -= mLoadedUserTime;
7478                } else if (which == STATS_SINCE_UNPLUGGED) {
7479                    val -= mUnpluggedUserTime;
7480                }
7481                return val;
7482            }
7483
7484            @Override
7485            public long getSystemTime(int which) {
7486                long val = mSystemTime;
7487                if (which == STATS_CURRENT) {
7488                    val -= mLoadedSystemTime;
7489                } else if (which == STATS_SINCE_UNPLUGGED) {
7490                    val -= mUnpluggedSystemTime;
7491                }
7492                return val;
7493            }
7494
7495            @Override
7496            public long getForegroundTime(int which) {
7497                long val = mForegroundTime;
7498                if (which == STATS_CURRENT) {
7499                    val -= mLoadedForegroundTime;
7500                } else if (which == STATS_SINCE_UNPLUGGED) {
7501                    val -= mUnpluggedForegroundTime;
7502                }
7503                return val;
7504            }
7505
7506            @Override
7507            public int getStarts(int which) {
7508                int val = mStarts;
7509                if (which == STATS_CURRENT) {
7510                    val -= mLoadedStarts;
7511                } else if (which == STATS_SINCE_UNPLUGGED) {
7512                    val -= mUnpluggedStarts;
7513                }
7514                return val;
7515            }
7516
7517            @Override
7518            public int getNumCrashes(int which) {
7519                int val = mNumCrashes;
7520                if (which == STATS_CURRENT) {
7521                    val -= mLoadedNumCrashes;
7522                } else if (which == STATS_SINCE_UNPLUGGED) {
7523                    val -= mUnpluggedNumCrashes;
7524                }
7525                return val;
7526            }
7527
7528            @Override
7529            public int getNumAnrs(int which) {
7530                int val = mNumAnrs;
7531                if (which == STATS_CURRENT) {
7532                    val -= mLoadedNumAnrs;
7533                } else if (which == STATS_SINCE_UNPLUGGED) {
7534                    val -= mUnpluggedNumAnrs;
7535                }
7536                return val;
7537            }
7538        }
7539
7540        /**
7541         * The statistics associated with a particular package.
7542         */
7543        public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
7544            /**
7545             * BatteryStatsImpl that we are associated with.
7546             */
7547            protected BatteryStatsImpl mBsi;
7548
7549            /**
7550             * Number of times wakeup alarms have occurred for this app.
7551             */
7552            ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
7553
7554            /**
7555             * The statics we have collected for this package's services.
7556             */
7557            final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
7558
7559            public Pkg(BatteryStatsImpl bsi) {
7560                mBsi = bsi;
7561                mBsi.mOnBatteryScreenOffTimeBase.add(this);
7562            }
7563
7564            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
7565            }
7566
7567            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
7568            }
7569
7570            void detach() {
7571                mBsi.mOnBatteryScreenOffTimeBase.remove(this);
7572            }
7573
7574            void readFromParcelLocked(Parcel in) {
7575                int numWA = in.readInt();
7576                mWakeupAlarms.clear();
7577                for (int i=0; i<numWA; i++) {
7578                    String tag = in.readString();
7579                    mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryTimeBase, in));
7580                }
7581
7582                int numServs = in.readInt();
7583                mServiceStats.clear();
7584                for (int m = 0; m < numServs; m++) {
7585                    String serviceName = in.readString();
7586                    Uid.Pkg.Serv serv = new Serv(mBsi);
7587                    mServiceStats.put(serviceName, serv);
7588
7589                    serv.readFromParcelLocked(in);
7590                }
7591            }
7592
7593            void writeToParcelLocked(Parcel out) {
7594                int numWA = mWakeupAlarms.size();
7595                out.writeInt(numWA);
7596                for (int i=0; i<numWA; i++) {
7597                    out.writeString(mWakeupAlarms.keyAt(i));
7598                    mWakeupAlarms.valueAt(i).writeToParcel(out);
7599                }
7600
7601                final int NS = mServiceStats.size();
7602                out.writeInt(NS);
7603                for (int i=0; i<NS; i++) {
7604                    out.writeString(mServiceStats.keyAt(i));
7605                    Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
7606                    serv.writeToParcelLocked(out);
7607                }
7608            }
7609
7610            @Override
7611            public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
7612                return mWakeupAlarms;
7613            }
7614
7615            public void noteWakeupAlarmLocked(String tag) {
7616                Counter c = mWakeupAlarms.get(tag);
7617                if (c == null) {
7618                    c = new Counter(mBsi.mOnBatteryTimeBase);
7619                    mWakeupAlarms.put(tag, c);
7620                }
7621                c.stepAtomic();
7622            }
7623
7624            @Override
7625            public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
7626                return mServiceStats;
7627            }
7628
7629            /**
7630             * The statistics associated with a particular service.
7631             */
7632            public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
7633                /**
7634                 * BatteryStatsImpl that we are associated with.
7635                 */
7636                protected BatteryStatsImpl mBsi;
7637
7638                /**
7639                 * The android package in which this service resides.
7640                 */
7641                protected Pkg mPkg;
7642
7643                /**
7644                 * Total time (ms in battery uptime) the service has been left started.
7645                 */
7646                protected long mStartTime;
7647
7648                /**
7649                 * If service has been started and not yet stopped, this is
7650                 * when it was started.
7651                 */
7652                protected long mRunningSince;
7653
7654                /**
7655                 * True if we are currently running.
7656                 */
7657                protected boolean mRunning;
7658
7659                /**
7660                 * Total number of times startService() has been called.
7661                 */
7662                protected int mStarts;
7663
7664                /**
7665                 * Total time (ms in battery uptime) the service has been left launched.
7666                 */
7667                protected long mLaunchedTime;
7668
7669                /**
7670                 * If service has been launched and not yet exited, this is
7671                 * when it was launched (ms in battery uptime).
7672                 */
7673                protected long mLaunchedSince;
7674
7675                /**
7676                 * True if we are currently launched.
7677                 */
7678                protected boolean mLaunched;
7679
7680                /**
7681                 * Total number times the service has been launched.
7682                 */
7683                protected int mLaunches;
7684
7685                /**
7686                 * The amount of time spent started loaded from a previous save
7687                 * (ms in battery uptime).
7688                 */
7689                protected long mLoadedStartTime;
7690
7691                /**
7692                 * The number of starts loaded from a previous save.
7693                 */
7694                protected int mLoadedStarts;
7695
7696                /**
7697                 * The number of launches loaded from a previous save.
7698                 */
7699                protected int mLoadedLaunches;
7700
7701                /**
7702                 * The amount of time spent started as of the last run (ms
7703                 * in battery uptime).
7704                 */
7705                protected long mLastStartTime;
7706
7707                /**
7708                 * The number of starts as of the last run.
7709                 */
7710                protected int mLastStarts;
7711
7712                /**
7713                 * The number of launches as of the last run.
7714                 */
7715                protected int mLastLaunches;
7716
7717                /**
7718                 * The amount of time spent started when last unplugged (ms
7719                 * in battery uptime).
7720                 */
7721                protected long mUnpluggedStartTime;
7722
7723                /**
7724                 * The number of starts when last unplugged.
7725                 */
7726                protected int mUnpluggedStarts;
7727
7728                /**
7729                 * The number of launches when last unplugged.
7730                 */
7731                protected int mUnpluggedLaunches;
7732
7733                /**
7734                 * Construct a Serv. Also adds it to the on-battery time base as a listener.
7735                 */
7736                public Serv(BatteryStatsImpl bsi) {
7737                    mBsi = bsi;
7738                    mBsi.mOnBatteryTimeBase.add(this);
7739                }
7740
7741                public void onTimeStarted(long elapsedRealtime, long baseUptime,
7742                        long baseRealtime) {
7743                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
7744                    mUnpluggedStarts = mStarts;
7745                    mUnpluggedLaunches = mLaunches;
7746                }
7747
7748                public void onTimeStopped(long elapsedRealtime, long baseUptime,
7749                        long baseRealtime) {
7750                }
7751
7752                /**
7753                 * Remove this Serv as a listener from the time base.
7754                 */
7755                public void detach() {
7756                    mBsi.mOnBatteryTimeBase.remove(this);
7757                }
7758
7759                public void readFromParcelLocked(Parcel in) {
7760                    mStartTime = in.readLong();
7761                    mRunningSince = in.readLong();
7762                    mRunning = in.readInt() != 0;
7763                    mStarts = in.readInt();
7764                    mLaunchedTime = in.readLong();
7765                    mLaunchedSince = in.readLong();
7766                    mLaunched = in.readInt() != 0;
7767                    mLaunches = in.readInt();
7768                    mLoadedStartTime = in.readLong();
7769                    mLoadedStarts = in.readInt();
7770                    mLoadedLaunches = in.readInt();
7771                    mLastStartTime = 0;
7772                    mLastStarts = 0;
7773                    mLastLaunches = 0;
7774                    mUnpluggedStartTime = in.readLong();
7775                    mUnpluggedStarts = in.readInt();
7776                    mUnpluggedLaunches = in.readInt();
7777                }
7778
7779                public void writeToParcelLocked(Parcel out) {
7780                    out.writeLong(mStartTime);
7781                    out.writeLong(mRunningSince);
7782                    out.writeInt(mRunning ? 1 : 0);
7783                    out.writeInt(mStarts);
7784                    out.writeLong(mLaunchedTime);
7785                    out.writeLong(mLaunchedSince);
7786                    out.writeInt(mLaunched ? 1 : 0);
7787                    out.writeInt(mLaunches);
7788                    out.writeLong(mLoadedStartTime);
7789                    out.writeInt(mLoadedStarts);
7790                    out.writeInt(mLoadedLaunches);
7791                    out.writeLong(mUnpluggedStartTime);
7792                    out.writeInt(mUnpluggedStarts);
7793                    out.writeInt(mUnpluggedLaunches);
7794                }
7795
7796                public long getLaunchTimeToNowLocked(long batteryUptime) {
7797                    if (!mLaunched) return mLaunchedTime;
7798                    return mLaunchedTime + batteryUptime - mLaunchedSince;
7799                }
7800
7801                public long getStartTimeToNowLocked(long batteryUptime) {
7802                    if (!mRunning) return mStartTime;
7803                    return mStartTime + batteryUptime - mRunningSince;
7804                }
7805
7806                public void startLaunchedLocked() {
7807                    if (!mLaunched) {
7808                        mLaunches++;
7809                        mLaunchedSince = mBsi.getBatteryUptimeLocked();
7810                        mLaunched = true;
7811                    }
7812                }
7813
7814                public void stopLaunchedLocked() {
7815                    if (mLaunched) {
7816                        long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
7817                        if (time > 0) {
7818                            mLaunchedTime += time;
7819                        } else {
7820                            mLaunches--;
7821                        }
7822                        mLaunched = false;
7823                    }
7824                }
7825
7826                public void startRunningLocked() {
7827                    if (!mRunning) {
7828                        mStarts++;
7829                        mRunningSince = mBsi.getBatteryUptimeLocked();
7830                        mRunning = true;
7831                    }
7832                }
7833
7834                public void stopRunningLocked() {
7835                    if (mRunning) {
7836                        long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
7837                        if (time > 0) {
7838                            mStartTime += time;
7839                        } else {
7840                            mStarts--;
7841                        }
7842                        mRunning = false;
7843                    }
7844                }
7845
7846                public BatteryStatsImpl getBatteryStats() {
7847                    return mBsi;
7848                }
7849
7850                @Override
7851                public int getLaunches(int which) {
7852                    int val = mLaunches;
7853                    if (which == STATS_CURRENT) {
7854                        val -= mLoadedLaunches;
7855                    } else if (which == STATS_SINCE_UNPLUGGED) {
7856                        val -= mUnpluggedLaunches;
7857                    }
7858                    return val;
7859                }
7860
7861                @Override
7862                public long getStartTime(long now, int which) {
7863                    long val = getStartTimeToNowLocked(now);
7864                    if (which == STATS_CURRENT) {
7865                        val -= mLoadedStartTime;
7866                    } else if (which == STATS_SINCE_UNPLUGGED) {
7867                        val -= mUnpluggedStartTime;
7868                    }
7869                    return val;
7870                }
7871
7872                @Override
7873                public int getStarts(int which) {
7874                    int val = mStarts;
7875                    if (which == STATS_CURRENT) {
7876                        val -= mLoadedStarts;
7877                    } else if (which == STATS_SINCE_UNPLUGGED) {
7878                        val -= mUnpluggedStarts;
7879                    }
7880
7881                    return val;
7882                }
7883            }
7884
7885            final Serv newServiceStatsLocked() {
7886                return new Serv(mBsi);
7887            }
7888        }
7889
7890        /**
7891         * Retrieve the statistics object for a particular process, creating
7892         * if needed.
7893         */
7894        public Proc getProcessStatsLocked(String name) {
7895            Proc ps = mProcessStats.get(name);
7896            if (ps == null) {
7897                ps = new Proc(mBsi, name);
7898                mProcessStats.put(name, ps);
7899            }
7900
7901            return ps;
7902        }
7903
7904        public void updateUidProcessStateLocked(int procState) {
7905            int uidRunningState;
7906            if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
7907                uidRunningState = ActivityManager.PROCESS_STATE_NONEXISTENT;
7908            } else if (procState == ActivityManager.PROCESS_STATE_TOP) {
7909                uidRunningState = PROCESS_STATE_TOP;
7910            } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
7911                // Persistent and other foreground states go here.
7912                uidRunningState = PROCESS_STATE_FOREGROUND_SERVICE;
7913            } else if (procState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
7914                uidRunningState = PROCESS_STATE_TOP_SLEEPING;
7915            } else if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
7916                // Persistent and other foreground states go here.
7917                uidRunningState = PROCESS_STATE_FOREGROUND;
7918            } else if (procState <= ActivityManager.PROCESS_STATE_RECEIVER) {
7919                uidRunningState = PROCESS_STATE_BACKGROUND;
7920            } else {
7921                uidRunningState = PROCESS_STATE_CACHED;
7922            }
7923
7924            if (mProcessState == uidRunningState) return;
7925
7926            final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
7927            final long uptimeMs = mBsi.mClocks.uptimeMillis();
7928
7929            if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
7930                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
7931            }
7932            mProcessState = uidRunningState;
7933            if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
7934                if (mProcessStateTimer[uidRunningState] == null) {
7935                    makeProcessState(uidRunningState, null);
7936                }
7937                mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
7938            }
7939
7940            updateBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
7941        }
7942
7943        public boolean updateBgTimeBase(long uptimeUs, long realtimeUs) {
7944            // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
7945            // also considered to be 'background' for our purposes, because it's not foreground.
7946            boolean isBgAndUnplugged = mBsi.mOnBatteryTimeBase.isRunning()
7947                    && mProcessState >= PROCESS_STATE_BACKGROUND;
7948            return mOnBatteryBackgroundTimeBase.setRunning(isBgAndUnplugged, uptimeUs, realtimeUs);
7949        }
7950
7951        public SparseArray<? extends Pid> getPidStats() {
7952            return mPids;
7953        }
7954
7955        public Pid getPidStatsLocked(int pid) {
7956            Pid p = mPids.get(pid);
7957            if (p == null) {
7958                p = new Pid();
7959                mPids.put(pid, p);
7960            }
7961            return p;
7962        }
7963
7964        /**
7965         * Retrieve the statistics object for a particular service, creating
7966         * if needed.
7967         */
7968        public Pkg getPackageStatsLocked(String name) {
7969            Pkg ps = mPackageStats.get(name);
7970            if (ps == null) {
7971                ps = new Pkg(mBsi);
7972                mPackageStats.put(name, ps);
7973            }
7974
7975            return ps;
7976        }
7977
7978        /**
7979         * Retrieve the statistics object for a particular service, creating
7980         * if needed.
7981         */
7982        public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
7983            Pkg ps = getPackageStatsLocked(pkg);
7984            Pkg.Serv ss = ps.mServiceStats.get(serv);
7985            if (ss == null) {
7986                ss = ps.newServiceStatsLocked();
7987                ps.mServiceStats.put(serv, ss);
7988            }
7989
7990            return ss;
7991        }
7992
7993        public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
7994            StopwatchTimer timer = mSyncStats.instantiateObject();
7995            timer.readSummaryFromParcelLocked(in);
7996            mSyncStats.add(name, timer);
7997        }
7998
7999        public void readJobSummaryFromParcelLocked(String name, Parcel in) {
8000            DualTimer timer = mJobStats.instantiateObject();
8001            timer.readSummaryFromParcelLocked(in);
8002            mJobStats.add(name, timer);
8003        }
8004
8005        public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
8006            Wakelock wl = new Wakelock(mBsi, this);
8007            mWakelockStats.add(wlName, wl);
8008            if (in.readInt() != 0) {
8009                wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
8010            }
8011            if (in.readInt() != 0) {
8012                wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
8013            }
8014            if (in.readInt() != 0) {
8015                wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
8016            }
8017            if (in.readInt() != 0) {
8018                wl.getStopwatchTimer(WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
8019            }
8020        }
8021
8022        public DualTimer getSensorTimerLocked(int sensor, boolean create) {
8023            Sensor se = mSensorStats.get(sensor);
8024            if (se == null) {
8025                if (!create) {
8026                    return null;
8027                }
8028                se = new Sensor(mBsi, this, sensor);
8029                mSensorStats.put(sensor, se);
8030            }
8031            DualTimer t = se.mTimer;
8032            if (t != null) {
8033                return t;
8034            }
8035            ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
8036            if (timers == null) {
8037                timers = new ArrayList<StopwatchTimer>();
8038                mBsi.mSensorTimers.put(sensor, timers);
8039            }
8040            t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
8041                    mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
8042            se.mTimer = t;
8043            return t;
8044        }
8045
8046        public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
8047            StopwatchTimer t = mSyncStats.startObject(name);
8048            if (t != null) {
8049                t.startRunningLocked(elapsedRealtimeMs);
8050            }
8051        }
8052
8053        public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
8054            StopwatchTimer t = mSyncStats.stopObject(name);
8055            if (t != null) {
8056                t.stopRunningLocked(elapsedRealtimeMs);
8057            }
8058        }
8059
8060        public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
8061            DualTimer t = mJobStats.startObject(name);
8062            if (t != null) {
8063                t.startRunningLocked(elapsedRealtimeMs);
8064            }
8065        }
8066
8067        public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
8068            DualTimer t = mJobStats.stopObject(name);
8069            if (t != null) {
8070                t.stopRunningLocked(elapsedRealtimeMs);
8071            }
8072        }
8073
8074        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
8075            Wakelock wl = mWakelockStats.startObject(name);
8076            if (wl != null) {
8077                wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
8078            }
8079            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
8080                Pid p = getPidStatsLocked(pid);
8081                if (p.mWakeNesting++ == 0) {
8082                    p.mWakeStartMs = elapsedRealtimeMs;
8083                }
8084            }
8085        }
8086
8087        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
8088            Wakelock wl = mWakelockStats.stopObject(name);
8089            if (wl != null) {
8090                wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
8091            }
8092            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
8093                Pid p = mPids.get(pid);
8094                if (p != null && p.mWakeNesting > 0) {
8095                    if (p.mWakeNesting-- == 1) {
8096                        p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
8097                        p.mWakeStartMs = 0;
8098                    }
8099                }
8100            }
8101        }
8102
8103        public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
8104            Proc p = getProcessStatsLocked(proc);
8105            if (p != null) {
8106                p.addExcessiveWake(overTime, usedTime);
8107            }
8108        }
8109
8110        public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
8111            Proc p = getProcessStatsLocked(proc);
8112            if (p != null) {
8113                p.addExcessiveCpu(overTime, usedTime);
8114            }
8115        }
8116
8117        public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
8118            DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
8119            t.startRunningLocked(elapsedRealtimeMs);
8120        }
8121
8122        public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
8123            // Don't create a timer if one doesn't already exist
8124            DualTimer t = getSensorTimerLocked(sensor, false);
8125            if (t != null) {
8126                t.stopRunningLocked(elapsedRealtimeMs);
8127            }
8128        }
8129
8130        public void noteStartGps(long elapsedRealtimeMs) {
8131            noteStartSensor(Sensor.GPS, elapsedRealtimeMs);
8132        }
8133
8134        public void noteStopGps(long elapsedRealtimeMs) {
8135            noteStopSensor(Sensor.GPS, elapsedRealtimeMs);
8136        }
8137
8138        public BatteryStatsImpl getBatteryStats() {
8139            return mBsi;
8140        }
8141    }
8142
8143    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
8144        this(new SystemClocks(), systemDir, handler, externalSync, null);
8145    }
8146
8147    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync,
8148                            PlatformIdleStateCallback cb) {
8149        this(new SystemClocks(), systemDir, handler, externalSync, cb);
8150    }
8151
8152    public BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
8153            ExternalStatsSync externalSync, PlatformIdleStateCallback cb) {
8154        init(clocks);
8155
8156        if (systemDir != null) {
8157            mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
8158                    new File(systemDir, "batterystats.bin.tmp"));
8159        } else {
8160            mFile = null;
8161        }
8162        mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
8163        mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
8164        mExternalSync = externalSync;
8165        mHandler = new MyHandler(handler.getLooper());
8166        mStartCount++;
8167        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
8168        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
8169            mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
8170                    mOnBatteryTimeBase);
8171        }
8172        mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
8173        mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
8174                mOnBatteryTimeBase);
8175        mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
8176                mOnBatteryTimeBase);
8177        mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
8178        mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
8179        mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
8180        mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
8181        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
8182            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
8183                    mOnBatteryTimeBase);
8184        }
8185        mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
8186                mOnBatteryTimeBase);
8187        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
8188            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
8189                    mOnBatteryTimeBase);
8190        }
8191        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8192            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
8193            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
8194        }
8195        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
8196        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
8197                NUM_BT_TX_LEVELS);
8198        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
8199                ModemActivityInfo.TX_POWER_LEVELS);
8200        mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
8201        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
8202                mOnBatteryTimeBase);
8203        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
8204        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
8205        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
8206        mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
8207        mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
8208        for (int i=0; i<NUM_WIFI_STATES; i++) {
8209            mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
8210                    mOnBatteryTimeBase);
8211        }
8212        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
8213            mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
8214                    mOnBatteryTimeBase);
8215        }
8216        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
8217            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
8218                    mOnBatteryTimeBase);
8219        }
8220        mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
8221        mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
8222        mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
8223        mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
8224        mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
8225        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
8226        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
8227        mOnBattery = mOnBatteryInternal = false;
8228        long uptime = mClocks.uptimeMillis() * 1000;
8229        long realtime = mClocks.elapsedRealtime() * 1000;
8230        initTimes(uptime, realtime);
8231        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
8232        mDischargeStartLevel = 0;
8233        mDischargeUnplugLevel = 0;
8234        mDischargePlugLevel = -1;
8235        mDischargeCurrentLevel = 0;
8236        mCurrentBatteryLevel = 0;
8237        initDischarge();
8238        clearHistoryLocked();
8239        updateDailyDeadlineLocked();
8240        mPlatformIdleStateCallback = cb;
8241    }
8242
8243    public BatteryStatsImpl(Parcel p) {
8244        this(new SystemClocks(), p);
8245    }
8246
8247    public BatteryStatsImpl(Clocks clocks, Parcel p) {
8248        init(clocks);
8249        mFile = null;
8250        mCheckinFile = null;
8251        mDailyFile = null;
8252        mHandler = null;
8253        mExternalSync = null;
8254        clearHistoryLocked();
8255        readFromParcel(p);
8256        mPlatformIdleStateCallback = null;
8257    }
8258
8259    public void setPowerProfile(PowerProfile profile) {
8260        synchronized (this) {
8261            mPowerProfile = profile;
8262
8263            // We need to initialize the KernelCpuSpeedReaders to read from
8264            // the first cpu of each core. Once we have the PowerProfile, we have access to this
8265            // information.
8266            final int numClusters = mPowerProfile.getNumCpuClusters();
8267            mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
8268            int firstCpuOfCluster = 0;
8269            for (int i = 0; i < numClusters; i++) {
8270                final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
8271                mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
8272                        numSpeedSteps);
8273                firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
8274            }
8275
8276            if (mEstimatedBatteryCapacity == -1) {
8277                // Initialize the estimated battery capacity to a known preset one.
8278                mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
8279            }
8280        }
8281    }
8282
8283    public void setCallback(BatteryCallback cb) {
8284        mCallback = cb;
8285    }
8286
8287    public void setRadioScanningTimeout(long timeout) {
8288        if (mPhoneSignalScanningTimer != null) {
8289            mPhoneSignalScanningTimer.setTimeout(timeout);
8290        }
8291    }
8292
8293    public void updateDailyDeadlineLocked() {
8294        // Get the current time.
8295        long currentTime = mDailyStartTime = System.currentTimeMillis();
8296        Calendar calDeadline = Calendar.getInstance();
8297        calDeadline.setTimeInMillis(currentTime);
8298
8299        // Move time up to the next day, ranging from 1am to 3pm.
8300        calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
8301        calDeadline.set(Calendar.MILLISECOND, 0);
8302        calDeadline.set(Calendar.SECOND, 0);
8303        calDeadline.set(Calendar.MINUTE, 0);
8304        calDeadline.set(Calendar.HOUR_OF_DAY, 1);
8305        mNextMinDailyDeadline = calDeadline.getTimeInMillis();
8306        calDeadline.set(Calendar.HOUR_OF_DAY, 3);
8307        mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
8308    }
8309
8310    public void recordDailyStatsIfNeededLocked(boolean settled) {
8311        long currentTime = System.currentTimeMillis();
8312        if (currentTime >= mNextMaxDailyDeadline) {
8313            recordDailyStatsLocked();
8314        } else if (settled && currentTime >= mNextMinDailyDeadline) {
8315            recordDailyStatsLocked();
8316        } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
8317            recordDailyStatsLocked();
8318        }
8319    }
8320
8321    public void recordDailyStatsLocked() {
8322        DailyItem item = new DailyItem();
8323        item.mStartTime = mDailyStartTime;
8324        item.mEndTime = System.currentTimeMillis();
8325        boolean hasData = false;
8326        if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
8327            hasData = true;
8328            item.mDischargeSteps = new LevelStepTracker(
8329                    mDailyDischargeStepTracker.mNumStepDurations,
8330                    mDailyDischargeStepTracker.mStepDurations);
8331        }
8332        if (mDailyChargeStepTracker.mNumStepDurations > 0) {
8333            hasData = true;
8334            item.mChargeSteps = new LevelStepTracker(
8335                    mDailyChargeStepTracker.mNumStepDurations,
8336                    mDailyChargeStepTracker.mStepDurations);
8337        }
8338        if (mDailyPackageChanges != null) {
8339            hasData = true;
8340            item.mPackageChanges = mDailyPackageChanges;
8341            mDailyPackageChanges = null;
8342        }
8343        mDailyDischargeStepTracker.init();
8344        mDailyChargeStepTracker.init();
8345        updateDailyDeadlineLocked();
8346
8347        if (hasData) {
8348            mDailyItems.add(item);
8349            while (mDailyItems.size() > MAX_DAILY_ITEMS) {
8350                mDailyItems.remove(0);
8351            }
8352            final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
8353            try {
8354                XmlSerializer out = new FastXmlSerializer();
8355                out.setOutput(memStream, StandardCharsets.UTF_8.name());
8356                writeDailyItemsLocked(out);
8357                BackgroundThread.getHandler().post(new Runnable() {
8358                    @Override
8359                    public void run() {
8360                        synchronized (mCheckinFile) {
8361                            FileOutputStream stream = null;
8362                            try {
8363                                stream = mDailyFile.startWrite();
8364                                memStream.writeTo(stream);
8365                                stream.flush();
8366                                FileUtils.sync(stream);
8367                                stream.close();
8368                                mDailyFile.finishWrite(stream);
8369                            } catch (IOException e) {
8370                                Slog.w("BatteryStats",
8371                                        "Error writing battery daily items", e);
8372                                mDailyFile.failWrite(stream);
8373                            }
8374                        }
8375                    }
8376                });
8377            } catch (IOException e) {
8378            }
8379        }
8380    }
8381
8382    private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
8383        StringBuilder sb = new StringBuilder(64);
8384        out.startDocument(null, true);
8385        out.startTag(null, "daily-items");
8386        for (int i=0; i<mDailyItems.size(); i++) {
8387            final DailyItem dit = mDailyItems.get(i);
8388            out.startTag(null, "item");
8389            out.attribute(null, "start", Long.toString(dit.mStartTime));
8390            out.attribute(null, "end", Long.toString(dit.mEndTime));
8391            writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
8392            writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
8393            if (dit.mPackageChanges != null) {
8394                for (int j=0; j<dit.mPackageChanges.size(); j++) {
8395                    PackageChange pc = dit.mPackageChanges.get(j);
8396                    if (pc.mUpdate) {
8397                        out.startTag(null, "upd");
8398                        out.attribute(null, "pkg", pc.mPackageName);
8399                        out.attribute(null, "ver", Integer.toString(pc.mVersionCode));
8400                        out.endTag(null, "upd");
8401                    } else {
8402                        out.startTag(null, "rem");
8403                        out.attribute(null, "pkg", pc.mPackageName);
8404                        out.endTag(null, "rem");
8405                    }
8406                }
8407            }
8408            out.endTag(null, "item");
8409        }
8410        out.endTag(null, "daily-items");
8411        out.endDocument();
8412    }
8413
8414    private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
8415            StringBuilder tmpBuilder) throws IOException {
8416        if (steps != null) {
8417            out.startTag(null, tag);
8418            out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
8419            for (int i=0; i<steps.mNumStepDurations; i++) {
8420                out.startTag(null, "s");
8421                tmpBuilder.setLength(0);
8422                steps.encodeEntryAt(i, tmpBuilder);
8423                out.attribute(null, "v", tmpBuilder.toString());
8424                out.endTag(null, "s");
8425            }
8426            out.endTag(null, tag);
8427        }
8428    }
8429
8430    public void readDailyStatsLocked() {
8431        Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
8432        mDailyItems.clear();
8433        FileInputStream stream;
8434        try {
8435            stream = mDailyFile.openRead();
8436        } catch (FileNotFoundException e) {
8437            return;
8438        }
8439        try {
8440            XmlPullParser parser = Xml.newPullParser();
8441            parser.setInput(stream, StandardCharsets.UTF_8.name());
8442            readDailyItemsLocked(parser);
8443        } catch (XmlPullParserException e) {
8444        } finally {
8445            try {
8446                stream.close();
8447            } catch (IOException e) {
8448            }
8449        }
8450    }
8451
8452    private void readDailyItemsLocked(XmlPullParser parser) {
8453        try {
8454            int type;
8455            while ((type = parser.next()) != XmlPullParser.START_TAG
8456                    && type != XmlPullParser.END_DOCUMENT) {
8457                ;
8458            }
8459
8460            if (type != XmlPullParser.START_TAG) {
8461                throw new IllegalStateException("no start tag found");
8462            }
8463
8464            int outerDepth = parser.getDepth();
8465            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
8466                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
8467                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
8468                    continue;
8469                }
8470
8471                String tagName = parser.getName();
8472                if (tagName.equals("item")) {
8473                    readDailyItemTagLocked(parser);
8474                } else {
8475                    Slog.w(TAG, "Unknown element under <daily-items>: "
8476                            + parser.getName());
8477                    XmlUtils.skipCurrentTag(parser);
8478                }
8479            }
8480
8481        } catch (IllegalStateException e) {
8482            Slog.w(TAG, "Failed parsing daily " + e);
8483        } catch (NullPointerException e) {
8484            Slog.w(TAG, "Failed parsing daily " + e);
8485        } catch (NumberFormatException e) {
8486            Slog.w(TAG, "Failed parsing daily " + e);
8487        } catch (XmlPullParserException e) {
8488            Slog.w(TAG, "Failed parsing daily " + e);
8489        } catch (IOException e) {
8490            Slog.w(TAG, "Failed parsing daily " + e);
8491        } catch (IndexOutOfBoundsException e) {
8492            Slog.w(TAG, "Failed parsing daily " + e);
8493        }
8494    }
8495
8496    void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
8497            XmlPullParserException, IOException {
8498        DailyItem dit = new DailyItem();
8499        String attr = parser.getAttributeValue(null, "start");
8500        if (attr != null) {
8501            dit.mStartTime = Long.parseLong(attr);
8502        }
8503        attr = parser.getAttributeValue(null, "end");
8504        if (attr != null) {
8505            dit.mEndTime = Long.parseLong(attr);
8506        }
8507        int outerDepth = parser.getDepth();
8508        int type;
8509        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
8510                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
8511            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
8512                continue;
8513            }
8514
8515            String tagName = parser.getName();
8516            if (tagName.equals("dis")) {
8517                readDailyItemTagDetailsLocked(parser, dit, false, "dis");
8518            } else if (tagName.equals("chg")) {
8519                readDailyItemTagDetailsLocked(parser, dit, true, "chg");
8520            } else if (tagName.equals("upd")) {
8521                if (dit.mPackageChanges == null) {
8522                    dit.mPackageChanges = new ArrayList<>();
8523                }
8524                PackageChange pc = new PackageChange();
8525                pc.mUpdate = true;
8526                pc.mPackageName = parser.getAttributeValue(null, "pkg");
8527                String verStr = parser.getAttributeValue(null, "ver");
8528                pc.mVersionCode = verStr != null ? Integer.parseInt(verStr) : 0;
8529                dit.mPackageChanges.add(pc);
8530                XmlUtils.skipCurrentTag(parser);
8531            } else if (tagName.equals("rem")) {
8532                if (dit.mPackageChanges == null) {
8533                    dit.mPackageChanges = new ArrayList<>();
8534                }
8535                PackageChange pc = new PackageChange();
8536                pc.mUpdate = false;
8537                pc.mPackageName = parser.getAttributeValue(null, "pkg");
8538                dit.mPackageChanges.add(pc);
8539                XmlUtils.skipCurrentTag(parser);
8540            } else {
8541                Slog.w(TAG, "Unknown element under <item>: "
8542                        + parser.getName());
8543                XmlUtils.skipCurrentTag(parser);
8544            }
8545        }
8546        mDailyItems.add(dit);
8547    }
8548
8549    void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
8550            String tag)
8551            throws NumberFormatException, XmlPullParserException, IOException {
8552        final String numAttr = parser.getAttributeValue(null, "n");
8553        if (numAttr == null) {
8554            Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
8555            XmlUtils.skipCurrentTag(parser);
8556            return;
8557        }
8558        final int num = Integer.parseInt(numAttr);
8559        LevelStepTracker steps = new LevelStepTracker(num);
8560        if (isCharge) {
8561            dit.mChargeSteps = steps;
8562        } else {
8563            dit.mDischargeSteps = steps;
8564        }
8565        int i = 0;
8566        int outerDepth = parser.getDepth();
8567        int type;
8568        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
8569                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
8570            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
8571                continue;
8572            }
8573
8574            String tagName = parser.getName();
8575            if ("s".equals(tagName)) {
8576                if (i < num) {
8577                    String valueAttr = parser.getAttributeValue(null, "v");
8578                    if (valueAttr != null) {
8579                        steps.decodeEntryAt(i, valueAttr);
8580                        i++;
8581                    }
8582                }
8583            } else {
8584                Slog.w(TAG, "Unknown element under <" + tag + ">: "
8585                        + parser.getName());
8586                XmlUtils.skipCurrentTag(parser);
8587            }
8588        }
8589        steps.mNumStepDurations = i;
8590    }
8591
8592    @Override
8593    public DailyItem getDailyItemLocked(int daysAgo) {
8594        int index = mDailyItems.size()-1-daysAgo;
8595        return index >= 0 ? mDailyItems.get(index) : null;
8596    }
8597
8598    @Override
8599    public long getCurrentDailyStartTime() {
8600        return mDailyStartTime;
8601    }
8602
8603    @Override
8604    public long getNextMinDailyDeadline() {
8605        return mNextMinDailyDeadline;
8606    }
8607
8608    @Override
8609    public long getNextMaxDailyDeadline() {
8610        return mNextMaxDailyDeadline;
8611    }
8612
8613    @Override
8614    public boolean startIteratingOldHistoryLocked() {
8615        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
8616                + " pos=" + mHistoryBuffer.dataPosition());
8617        if ((mHistoryIterator = mHistory) == null) {
8618            return false;
8619        }
8620        mHistoryBuffer.setDataPosition(0);
8621        mHistoryReadTmp.clear();
8622        mReadOverflow = false;
8623        mIteratingHistory = true;
8624        return true;
8625    }
8626
8627    @Override
8628    public boolean getNextOldHistoryLocked(HistoryItem out) {
8629        boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
8630        if (!end) {
8631            readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
8632            mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
8633        }
8634        HistoryItem cur = mHistoryIterator;
8635        if (cur == null) {
8636            if (!mReadOverflow && !end) {
8637                Slog.w(TAG, "Old history ends before new history!");
8638            }
8639            return false;
8640        }
8641        out.setTo(cur);
8642        mHistoryIterator = cur.next;
8643        if (!mReadOverflow) {
8644            if (end) {
8645                Slog.w(TAG, "New history ends before old history!");
8646            } else if (!out.same(mHistoryReadTmp)) {
8647                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
8648                pw.println("Histories differ!");
8649                pw.println("Old history:");
8650                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
8651                pw.println("New history:");
8652                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
8653                        true);
8654                pw.flush();
8655            }
8656        }
8657        return true;
8658    }
8659
8660    @Override
8661    public void finishIteratingOldHistoryLocked() {
8662        mIteratingHistory = false;
8663        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
8664        mHistoryIterator = null;
8665    }
8666
8667    public int getHistoryTotalSize() {
8668        return MAX_HISTORY_BUFFER;
8669    }
8670
8671    public int getHistoryUsedSize() {
8672        return mHistoryBuffer.dataSize();
8673    }
8674
8675    @Override
8676    public boolean startIteratingHistoryLocked() {
8677        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
8678                + " pos=" + mHistoryBuffer.dataPosition());
8679        if (mHistoryBuffer.dataSize() <= 0) {
8680            return false;
8681        }
8682        mHistoryBuffer.setDataPosition(0);
8683        mReadOverflow = false;
8684        mIteratingHistory = true;
8685        mReadHistoryStrings = new String[mHistoryTagPool.size()];
8686        mReadHistoryUids = new int[mHistoryTagPool.size()];
8687        mReadHistoryChars = 0;
8688        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
8689            final HistoryTag tag = ent.getKey();
8690            final int idx = ent.getValue();
8691            mReadHistoryStrings[idx] = tag.string;
8692            mReadHistoryUids[idx] = tag.uid;
8693            mReadHistoryChars += tag.string.length() + 1;
8694        }
8695        return true;
8696    }
8697
8698    @Override
8699    public int getHistoryStringPoolSize() {
8700        return mReadHistoryStrings.length;
8701    }
8702
8703    @Override
8704    public int getHistoryStringPoolBytes() {
8705        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
8706        // Each string character is 2 bytes.
8707        return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
8708    }
8709
8710    @Override
8711    public String getHistoryTagPoolString(int index) {
8712        return mReadHistoryStrings[index];
8713    }
8714
8715    @Override
8716    public int getHistoryTagPoolUid(int index) {
8717        return mReadHistoryUids[index];
8718    }
8719
8720    @Override
8721    public boolean getNextHistoryLocked(HistoryItem out) {
8722        final int pos = mHistoryBuffer.dataPosition();
8723        if (pos == 0) {
8724            out.clear();
8725        }
8726        boolean end = pos >= mHistoryBuffer.dataSize();
8727        if (end) {
8728            return false;
8729        }
8730
8731        final long lastRealtime = out.time;
8732        final long lastWalltime = out.currentTime;
8733        readHistoryDelta(mHistoryBuffer, out);
8734        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
8735                && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
8736            out.currentTime = lastWalltime + (out.time - lastRealtime);
8737        }
8738        return true;
8739    }
8740
8741    @Override
8742    public void finishIteratingHistoryLocked() {
8743        mIteratingHistory = false;
8744        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
8745        mReadHistoryStrings = null;
8746    }
8747
8748    @Override
8749    public long getHistoryBaseTime() {
8750        return mHistoryBaseTime;
8751    }
8752
8753    @Override
8754    public int getStartCount() {
8755        return mStartCount;
8756    }
8757
8758    public boolean isOnBattery() {
8759        return mOnBattery;
8760    }
8761
8762    public boolean isCharging() {
8763        return mCharging;
8764    }
8765
8766    public boolean isScreenOn() {
8767        return mScreenState == Display.STATE_ON;
8768    }
8769
8770    void initTimes(long uptime, long realtime) {
8771        mStartClockTime = System.currentTimeMillis();
8772        mOnBatteryTimeBase.init(uptime, realtime);
8773        mOnBatteryScreenOffTimeBase.init(uptime, realtime);
8774        mRealtime = 0;
8775        mUptime = 0;
8776        mRealtimeStart = realtime;
8777        mUptimeStart = uptime;
8778    }
8779
8780    void initDischarge() {
8781        mLowDischargeAmountSinceCharge = 0;
8782        mHighDischargeAmountSinceCharge = 0;
8783        mDischargeAmountScreenOn = 0;
8784        mDischargeAmountScreenOnSinceCharge = 0;
8785        mDischargeAmountScreenOff = 0;
8786        mDischargeAmountScreenOffSinceCharge = 0;
8787        mDischargeStepTracker.init();
8788        mChargeStepTracker.init();
8789        mDischargeScreenOffCounter.reset(false);
8790        mDischargeCounter.reset(false);
8791    }
8792
8793    public void resetAllStatsCmdLocked() {
8794        resetAllStatsLocked();
8795        final long mSecUptime = mClocks.uptimeMillis();
8796        long uptime = mSecUptime * 1000;
8797        long mSecRealtime = mClocks.elapsedRealtime();
8798        long realtime = mSecRealtime * 1000;
8799        mDischargeStartLevel = mHistoryCur.batteryLevel;
8800        pullPendingStateUpdatesLocked();
8801        addHistoryRecordLocked(mSecRealtime, mSecUptime);
8802        mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
8803                = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
8804        mOnBatteryTimeBase.reset(uptime, realtime);
8805        mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
8806        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
8807            if (mScreenState == Display.STATE_ON) {
8808                mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
8809                mDischargeScreenOffUnplugLevel = 0;
8810            } else {
8811                mDischargeScreenOnUnplugLevel = 0;
8812                mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
8813            }
8814            mDischargeAmountScreenOn = 0;
8815            mDischargeAmountScreenOff = 0;
8816        }
8817        initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
8818    }
8819
8820    private void resetAllStatsLocked() {
8821        final long uptimeMillis = mClocks.uptimeMillis();
8822        final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
8823        mStartCount = 0;
8824        initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
8825        mScreenOnTimer.reset(false);
8826        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
8827            mScreenBrightnessTimer[i].reset(false);
8828        }
8829
8830        if (mPowerProfile != null) {
8831            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
8832        } else {
8833            mEstimatedBatteryCapacity = -1;
8834        }
8835        mInteractiveTimer.reset(false);
8836        mPowerSaveModeEnabledTimer.reset(false);
8837        mLastIdleTimeStart = elapsedRealtimeMillis;
8838        mLongestLightIdleTime = 0;
8839        mLongestFullIdleTime = 0;
8840        mDeviceIdleModeLightTimer.reset(false);
8841        mDeviceIdleModeFullTimer.reset(false);
8842        mDeviceLightIdlingTimer.reset(false);
8843        mDeviceIdlingTimer.reset(false);
8844        mPhoneOnTimer.reset(false);
8845        mAudioOnTimer.reset(false);
8846        mVideoOnTimer.reset(false);
8847        mFlashlightOnTimer.reset(false);
8848        mCameraOnTimer.reset(false);
8849        mBluetoothScanTimer.reset(false);
8850        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
8851            mPhoneSignalStrengthsTimer[i].reset(false);
8852        }
8853        mPhoneSignalScanningTimer.reset(false);
8854        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
8855            mPhoneDataConnectionsTimer[i].reset(false);
8856        }
8857        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8858            mNetworkByteActivityCounters[i].reset(false);
8859            mNetworkPacketActivityCounters[i].reset(false);
8860        }
8861        mMobileRadioActiveTimer.reset(false);
8862        mMobileRadioActivePerAppTimer.reset(false);
8863        mMobileRadioActiveAdjustedTime.reset(false);
8864        mMobileRadioActiveUnknownTime.reset(false);
8865        mMobileRadioActiveUnknownCount.reset(false);
8866        mWifiOnTimer.reset(false);
8867        mGlobalWifiRunningTimer.reset(false);
8868        for (int i=0; i<NUM_WIFI_STATES; i++) {
8869            mWifiStateTimer[i].reset(false);
8870        }
8871        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
8872            mWifiSupplStateTimer[i].reset(false);
8873        }
8874        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
8875            mWifiSignalStrengthsTimer[i].reset(false);
8876        }
8877        mWifiActivity.reset(false);
8878        mBluetoothActivity.reset(false);
8879        mModemActivity.reset(false);
8880        mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
8881
8882        for (int i=0; i<mUidStats.size(); i++) {
8883            if (mUidStats.valueAt(i).reset()) {
8884                mUidStats.remove(mUidStats.keyAt(i));
8885                i--;
8886            }
8887        }
8888
8889        if (mKernelWakelockStats.size() > 0) {
8890            for (SamplingTimer timer : mKernelWakelockStats.values()) {
8891                mOnBatteryScreenOffTimeBase.remove(timer);
8892            }
8893            mKernelWakelockStats.clear();
8894        }
8895
8896        if (mKernelMemoryStats.size() > 0) {
8897            for (int i = 0; i < mKernelMemoryStats.size(); i++) {
8898                mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i));
8899            }
8900            mKernelMemoryStats.clear();
8901        }
8902
8903        if (mWakeupReasonStats.size() > 0) {
8904            for (SamplingTimer timer : mWakeupReasonStats.values()) {
8905                mOnBatteryTimeBase.remove(timer);
8906            }
8907            mWakeupReasonStats.clear();
8908        }
8909
8910        mLastHistoryStepDetails = null;
8911        mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
8912        mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
8913        mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
8914        mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
8915        mLastStepStatUserTime = mCurStepStatUserTime = 0;
8916        mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
8917        mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
8918        mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
8919        mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
8920        mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
8921
8922        initDischarge();
8923
8924        clearHistoryLocked();
8925    }
8926
8927    private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
8928        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
8929            if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
8930                // Not recording process starts/stops.
8931                continue;
8932            }
8933            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
8934            if (active == null) {
8935                continue;
8936            }
8937            for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
8938                SparseIntArray uids = ent.getValue();
8939                for (int j=0; j<uids.size(); j++) {
8940                    addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
8941                            uids.keyAt(j));
8942                }
8943            }
8944        }
8945    }
8946
8947    void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
8948        if (oldScreenOn) {
8949            int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
8950            if (diff > 0) {
8951                mDischargeAmountScreenOn += diff;
8952                mDischargeAmountScreenOnSinceCharge += diff;
8953            }
8954        } else {
8955            int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
8956            if (diff > 0) {
8957                mDischargeAmountScreenOff += diff;
8958                mDischargeAmountScreenOffSinceCharge += diff;
8959            }
8960        }
8961        if (newScreenOn) {
8962            mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
8963            mDischargeScreenOffUnplugLevel = 0;
8964        } else {
8965            mDischargeScreenOnUnplugLevel = 0;
8966            mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
8967        }
8968    }
8969
8970    public void pullPendingStateUpdatesLocked() {
8971        if (mOnBatteryInternal) {
8972            final boolean screenOn = mScreenState == Display.STATE_ON;
8973            updateDischargeScreenLevelsLocked(screenOn, screenOn);
8974        }
8975    }
8976
8977    private String[] mMobileIfaces = EmptyArray.STRING;
8978    private String[] mWifiIfaces = EmptyArray.STRING;
8979
8980    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
8981
8982    private static final int NETWORK_STATS_LAST = 0;
8983    private static final int NETWORK_STATS_NEXT = 1;
8984    private static final int NETWORK_STATS_DELTA = 2;
8985
8986    private NetworkStats[] mMobileNetworkStats;
8987    private NetworkStats[] mWifiNetworkStats;
8988
8989    /**
8990     * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
8991     * as a buffer of NetworkStats objects to cycle through when computing deltas.
8992     */
8993    private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
8994                                                    NetworkStats[] networkStatsBuffer)
8995            throws IOException {
8996        if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
8997                false)) {
8998            return null;
8999        }
9000
9001        final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
9002                ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
9003        networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
9004                networkStatsBuffer[NETWORK_STATS_LAST], null, null,
9005                networkStatsBuffer[NETWORK_STATS_DELTA]);
9006        networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
9007        networkStatsBuffer[NETWORK_STATS_LAST] = stats;
9008        return networkStatsBuffer[NETWORK_STATS_DELTA];
9009    }
9010
9011    /**
9012     * Distribute WiFi energy info and network traffic to apps.
9013     * @param info The energy information from the WiFi controller.
9014     */
9015    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
9016        if (DEBUG_ENERGY) {
9017            Slog.d(TAG, "Updating wifi stats");
9018        }
9019
9020        final long elapsedRealtimeMs = mClocks.elapsedRealtime();
9021        NetworkStats delta = null;
9022        try {
9023            if (!ArrayUtils.isEmpty(mWifiIfaces)) {
9024                delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
9025            }
9026        } catch (IOException e) {
9027            Slog.wtf(TAG, "Failed to get wifi network stats", e);
9028            return;
9029        }
9030
9031        if (!mOnBatteryInternal) {
9032            return;
9033        }
9034
9035        SparseLongArray rxPackets = new SparseLongArray();
9036        SparseLongArray txPackets = new SparseLongArray();
9037        long totalTxPackets = 0;
9038        long totalRxPackets = 0;
9039        if (delta != null) {
9040            final int size = delta.size();
9041            for (int i = 0; i < size; i++) {
9042                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
9043
9044                if (DEBUG_ENERGY) {
9045                    Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
9046                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
9047                            + " txPackets=" + entry.txPackets);
9048                }
9049
9050                if (entry.rxBytes == 0 && entry.txBytes == 0) {
9051                    // Skip the lookup below since there is no work to do.
9052                    continue;
9053                }
9054
9055                final Uid u = getUidStatsLocked(mapUid(entry.uid));
9056                if (entry.rxBytes != 0) {
9057                    u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
9058                            entry.rxPackets);
9059                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
9060                        u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
9061                                entry.rxPackets);
9062                    }
9063                    mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
9064                            entry.rxBytes);
9065                    mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
9066                            entry.rxPackets);
9067
9068                    rxPackets.put(u.getUid(), entry.rxPackets);
9069
9070                    // Sum the total number of packets so that the Rx Power can
9071                    // be evenly distributed amongst the apps.
9072                    totalRxPackets += entry.rxPackets;
9073                }
9074
9075                if (entry.txBytes != 0) {
9076                    u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
9077                            entry.txPackets);
9078                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
9079                        u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
9080                                entry.txPackets);
9081                    }
9082                    mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
9083                            entry.txBytes);
9084                    mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
9085                            entry.txPackets);
9086
9087                    txPackets.put(u.getUid(), entry.txPackets);
9088
9089                    // Sum the total number of packets so that the Tx Power can
9090                    // be evenly distributed amongst the apps.
9091                    totalTxPackets += entry.txPackets;
9092                }
9093            }
9094        }
9095
9096        if (info != null) {
9097            mHasWifiReporting = true;
9098
9099            // Measured in mAms
9100            final long txTimeMs = info.getControllerTxTimeMillis();
9101            final long rxTimeMs = info.getControllerRxTimeMillis();
9102            final long idleTimeMs = info.getControllerIdleTimeMillis();
9103            final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
9104
9105            long leftOverRxTimeMs = rxTimeMs;
9106            long leftOverTxTimeMs = txTimeMs;
9107
9108            if (DEBUG_ENERGY) {
9109                Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
9110                Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
9111                Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
9112                Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
9113                Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
9114            }
9115
9116            long totalWifiLockTimeMs = 0;
9117            long totalScanTimeMs = 0;
9118
9119            // On the first pass, collect some totals so that we can normalize power
9120            // calculations if we need to.
9121            final int uidStatsSize = mUidStats.size();
9122            for (int i = 0; i < uidStatsSize; i++) {
9123                final Uid uid = mUidStats.valueAt(i);
9124
9125                // Sum the total scan power for all apps.
9126                totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
9127                        elapsedRealtimeMs * 1000) / 1000;
9128
9129                // Sum the total time holding wifi lock for all apps.
9130                totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
9131                        elapsedRealtimeMs * 1000) / 1000;
9132            }
9133
9134            if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
9135                Slog.d(TAG, "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
9136                        + rxTimeMs + " ms). Normalizing scan time.");
9137            }
9138            if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
9139                Slog.d(TAG, "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
9140                        + txTimeMs + " ms). Normalizing scan time.");
9141            }
9142
9143            // Actually assign and distribute power usage to apps.
9144            for (int i = 0; i < uidStatsSize; i++) {
9145                final Uid uid = mUidStats.valueAt(i);
9146
9147                long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
9148                        elapsedRealtimeMs * 1000) / 1000;
9149                if (scanTimeSinceMarkMs > 0) {
9150                    // Set the new mark so that next time we get new data since this point.
9151                    uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
9152
9153                    long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
9154                    long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
9155
9156                    // Our total scan time is more than the reported Tx/Rx time.
9157                    // This is possible because the cost of a scan is approximate.
9158                    // Let's normalize the result so that we evenly blame each app
9159                    // scanning.
9160                    //
9161                    // This means that we may have apps that transmitted/received packets not be
9162                    // blamed for this, but this is fine as scans are relatively more expensive.
9163                    if (totalScanTimeMs > rxTimeMs) {
9164                        scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
9165                                totalScanTimeMs;
9166                    }
9167                    if (totalScanTimeMs > txTimeMs) {
9168                        scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
9169                                totalScanTimeMs;
9170                    }
9171
9172                    if (DEBUG_ENERGY) {
9173                        Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
9174                                + scanRxTimeSinceMarkMs + " ms  Tx:"
9175                                + scanTxTimeSinceMarkMs + " ms)");
9176                    }
9177
9178                    ControllerActivityCounterImpl activityCounter =
9179                            uid.getOrCreateWifiControllerActivityLocked();
9180                    activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
9181                    activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
9182                    leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
9183                    leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
9184                }
9185
9186                // Distribute evenly the power consumed while Idle to each app holding a WiFi
9187                // lock.
9188                final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
9189                        elapsedRealtimeMs * 1000) / 1000;
9190                if (wifiLockTimeSinceMarkMs > 0) {
9191                    // Set the new mark so that next time we get new data since this point.
9192                    uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
9193
9194                    final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
9195                            / totalWifiLockTimeMs;
9196                    if (DEBUG_ENERGY) {
9197                        Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
9198                                + myIdleTimeMs + " ms");
9199                    }
9200                    uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
9201                            .addCountLocked(myIdleTimeMs);
9202                }
9203            }
9204
9205            if (DEBUG_ENERGY) {
9206                Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
9207                Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
9208            }
9209
9210            // Distribute the remaining Tx power appropriately between all apps that transmitted
9211            // packets.
9212            for (int i = 0; i < txPackets.size(); i++) {
9213                final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
9214                final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets;
9215                if (DEBUG_ENERGY) {
9216                    Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
9217                }
9218                uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
9219                        .addCountLocked(myTxTimeMs);
9220            }
9221
9222            // Distribute the remaining Rx power appropriately between all apps that received
9223            // packets.
9224            for (int i = 0; i < rxPackets.size(); i++) {
9225                final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
9226                final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
9227                if (DEBUG_ENERGY) {
9228                    Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
9229                }
9230                uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
9231                        .addCountLocked(myRxTimeMs);
9232            }
9233
9234            // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
9235
9236            // Update WiFi controller stats.
9237            mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
9238            mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis());
9239            mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis());
9240
9241            // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
9242            final double opVolt = mPowerProfile.getAveragePower(
9243                    PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
9244            if (opVolt != 0) {
9245                // We store the power drain as mAms.
9246                mWifiActivity.getPowerCounter().addCountLocked(
9247                        (long)(info.getControllerEnergyUsed() / opVolt));
9248            }
9249        }
9250    }
9251
9252    /**
9253     * Distribute Cell radio energy info and network traffic to apps.
9254     */
9255    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs,
9256                                             final ModemActivityInfo activityInfo) {
9257        if (DEBUG_ENERGY) {
9258            Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
9259        }
9260
9261        NetworkStats delta = null;
9262        try {
9263            if (!ArrayUtils.isEmpty(mMobileIfaces)) {
9264                delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
9265            }
9266        } catch (IOException e) {
9267            Slog.wtf(TAG, "Failed to get mobile network stats", e);
9268            return;
9269        }
9270
9271        if (!mOnBatteryInternal) {
9272            return;
9273        }
9274
9275        long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
9276                elapsedRealtimeMs * 1000);
9277        mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
9278
9279        long totalRxPackets = 0;
9280        long totalTxPackets = 0;
9281        if (delta != null) {
9282            final int size = delta.size();
9283            for (int i = 0; i < size; i++) {
9284                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
9285                if (entry.rxPackets == 0 && entry.txPackets == 0) {
9286                    continue;
9287                }
9288
9289                if (DEBUG_ENERGY) {
9290                    Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
9291                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
9292                            + " txPackets=" + entry.txPackets);
9293                }
9294
9295                totalRxPackets += entry.rxPackets;
9296                totalTxPackets += entry.txPackets;
9297
9298                final Uid u = getUidStatsLocked(mapUid(entry.uid));
9299                u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
9300                u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
9301                if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
9302                    u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
9303                            entry.rxBytes, entry.rxPackets);
9304                    u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
9305                            entry.txBytes, entry.txPackets);
9306                }
9307
9308                mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
9309                        entry.rxBytes);
9310                mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
9311                        entry.txBytes);
9312                mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
9313                        entry.rxPackets);
9314                mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
9315                        entry.txPackets);
9316            }
9317
9318            // Now distribute proportional blame to the apps that did networking.
9319            long totalPackets = totalRxPackets + totalTxPackets;
9320            if (totalPackets > 0) {
9321                for (int i = 0; i < size; i++) {
9322                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
9323                    if (entry.rxPackets == 0 && entry.txPackets == 0) {
9324                        continue;
9325                    }
9326
9327                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
9328
9329                    // Distribute total radio active time in to this app.
9330                    final long appPackets = entry.rxPackets + entry.txPackets;
9331                    final long appRadioTime = (radioTime * appPackets) / totalPackets;
9332                    u.noteMobileRadioActiveTimeLocked(appRadioTime);
9333
9334                    // Remove this app from the totals, so that we don't lose any time
9335                    // due to rounding.
9336                    radioTime -= appRadioTime;
9337                    totalPackets -= appPackets;
9338
9339                    if (activityInfo != null) {
9340                        ControllerActivityCounterImpl activityCounter =
9341                                u.getOrCreateModemControllerActivityLocked();
9342                        if (totalRxPackets > 0 && entry.rxPackets > 0) {
9343                            final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
9344                                    / totalRxPackets;
9345                            activityCounter.getRxTimeCounter().addCountLocked(rxMs);
9346                        }
9347
9348                        if (totalTxPackets > 0 && entry.txPackets > 0) {
9349                            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
9350                                long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
9351                                txMs /= totalTxPackets;
9352                                activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
9353                            }
9354                        }
9355                    }
9356                }
9357            }
9358
9359            if (radioTime > 0) {
9360                // Whoops, there is some radio time we can't blame on an app!
9361                mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
9362                mMobileRadioActiveUnknownCount.addCountLocked(1);
9363            }
9364        }
9365
9366        if (activityInfo != null) {
9367            mHasModemReporting = true;
9368            mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis());
9369            mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
9370            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
9371                mModemActivity.getTxTimeCounters()[lvl]
9372                        .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
9373            }
9374
9375            // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
9376            final double opVolt = mPowerProfile.getAveragePower(
9377                    PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
9378            if (opVolt != 0) {
9379                // We store the power drain as mAms.
9380                mModemActivity.getPowerCounter().addCountLocked(
9381                        (long) (activityInfo.getEnergyUsed() / opVolt));
9382            }
9383        }
9384    }
9385
9386    /**
9387     * Distribute Bluetooth energy info and network traffic to apps.
9388     * @param info The energy information from the bluetooth controller.
9389     */
9390    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
9391        if (DEBUG_ENERGY) {
9392            Slog.d(TAG, "Updating bluetooth stats: " + info);
9393        }
9394
9395        if (info == null || !mOnBatteryInternal) {
9396            return;
9397        }
9398
9399        mHasBluetoothReporting = true;
9400
9401        final long elapsedRealtimeMs = mClocks.elapsedRealtime();
9402        final long rxTimeMs = info.getControllerRxTimeMillis();
9403        final long txTimeMs = info.getControllerTxTimeMillis();
9404
9405        if (DEBUG_ENERGY) {
9406            Slog.d(TAG, "------ BEGIN BLE power blaming ------");
9407            Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
9408            Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
9409            Slog.d(TAG, "  Idle Time:  " + info.getControllerIdleTimeMillis() + " ms");
9410        }
9411
9412        long totalScanTimeMs = 0;
9413
9414        final int uidCount = mUidStats.size();
9415        for (int i = 0; i < uidCount; i++) {
9416            final Uid u = mUidStats.valueAt(i);
9417            if (u.mBluetoothScanTimer == null) {
9418                continue;
9419            }
9420
9421            totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
9422                    elapsedRealtimeMs * 1000) / 1000;
9423        }
9424
9425        final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
9426        final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
9427
9428        if (DEBUG_ENERGY) {
9429            Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
9430                    + " TX=" + normalizeScanTxTime);
9431        }
9432
9433        long leftOverRxTimeMs = rxTimeMs;
9434        long leftOverTxTimeMs = txTimeMs;
9435
9436        for (int i = 0; i < uidCount; i++) {
9437            final Uid u = mUidStats.valueAt(i);
9438            if (u.mBluetoothScanTimer == null) {
9439                continue;
9440            }
9441
9442            long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
9443                    elapsedRealtimeMs * 1000) / 1000;
9444            if (scanTimeSinceMarkMs > 0) {
9445                // Set the new mark so that next time we get new data since this point.
9446                u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
9447
9448                long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
9449                long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
9450
9451                if (normalizeScanRxTime) {
9452                    // Scan time is longer than the total rx time in the controller,
9453                    // so distribute the scan time proportionately. This means regular traffic
9454                    // will not blamed, but scans are more expensive anyways.
9455                    scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
9456                }
9457
9458                if (normalizeScanTxTime) {
9459                    // Scan time is longer than the total tx time in the controller,
9460                    // so distribute the scan time proportionately. This means regular traffic
9461                    // will not blamed, but scans are more expensive anyways.
9462                    scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
9463                }
9464
9465                final ControllerActivityCounterImpl counter =
9466                        u.getOrCreateBluetoothControllerActivityLocked();
9467                counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
9468                counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
9469
9470                leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
9471                leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
9472            }
9473        }
9474
9475        if (DEBUG_ENERGY) {
9476            Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs
9477                    + " TX=" + leftOverTxTimeMs);
9478        }
9479
9480        //
9481        // Now distribute blame to apps that did bluetooth traffic.
9482        //
9483
9484        long totalTxBytes = 0;
9485        long totalRxBytes = 0;
9486
9487        final UidTraffic[] uidTraffic = info.getUidTraffic();
9488        final int numUids = uidTraffic != null ? uidTraffic.length : 0;
9489        for (int i = 0; i < numUids; i++) {
9490            final UidTraffic traffic = uidTraffic[i];
9491
9492            // Add to the global counters.
9493            mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
9494                    traffic.getRxBytes());
9495            mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(
9496                    traffic.getTxBytes());
9497
9498            // Add to the UID counters.
9499            final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
9500            u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0);
9501            u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0);
9502
9503            // Calculate the total traffic.
9504            totalTxBytes += traffic.getTxBytes();
9505            totalRxBytes += traffic.getRxBytes();
9506        }
9507
9508        if ((totalTxBytes != 0 || totalRxBytes != 0) &&
9509                (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) {
9510            for (int i = 0; i < numUids; i++) {
9511                final UidTraffic traffic = uidTraffic[i];
9512
9513                final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
9514                final ControllerActivityCounterImpl counter =
9515                        u.getOrCreateBluetoothControllerActivityLocked();
9516
9517                if (totalRxBytes > 0 && traffic.getRxBytes() > 0) {
9518                    final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes;
9519
9520                    if (DEBUG_ENERGY) {
9521                        Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes()
9522                                + " rx_time=" + timeRxMs);
9523                    }
9524                    counter.getRxTimeCounter().addCountLocked(timeRxMs);
9525                    leftOverRxTimeMs -= timeRxMs;
9526                }
9527
9528                if (totalTxBytes > 0 && traffic.getTxBytes() > 0) {
9529                    final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes;
9530
9531                    if (DEBUG_ENERGY) {
9532                        Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes()
9533                                + " tx_time=" + timeTxMs);
9534                    }
9535
9536                    counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
9537                    leftOverTxTimeMs -= timeTxMs;
9538                }
9539            }
9540        }
9541
9542        mBluetoothActivity.getRxTimeCounter().addCountLocked(
9543                info.getControllerRxTimeMillis());
9544        mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
9545                info.getControllerTxTimeMillis());
9546        mBluetoothActivity.getIdleTimeCounter().addCountLocked(
9547                info.getControllerIdleTimeMillis());
9548
9549        // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
9550        final double opVolt = mPowerProfile.getAveragePower(
9551                PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
9552        if (opVolt != 0) {
9553            // We store the power drain as mAms.
9554            mBluetoothActivity.getPowerCounter().addCountLocked(
9555                    (long) (info.getControllerEnergyUsed() / opVolt));
9556        }
9557    }
9558
9559    /**
9560     * Read and distribute kernel wake lock use across apps.
9561     */
9562    public void updateKernelWakelocksLocked() {
9563        final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
9564                mTmpWakelockStats);
9565        if (wakelockStats == null) {
9566            // Not crashing might make board bringup easier.
9567            Slog.w(TAG, "Couldn't get kernel wake lock stats");
9568            return;
9569        }
9570
9571        for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
9572            String name = ent.getKey();
9573            KernelWakelockStats.Entry kws = ent.getValue();
9574
9575            SamplingTimer kwlt = mKernelWakelockStats.get(name);
9576            if (kwlt == null) {
9577                kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
9578                mKernelWakelockStats.put(name, kwlt);
9579            }
9580
9581            kwlt.update(kws.mTotalTime, kws.mCount);
9582            kwlt.setUpdateVersion(kws.mVersion);
9583        }
9584
9585        int numWakelocksSetStale = 0;
9586        // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
9587        // this time.
9588        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
9589            SamplingTimer st = ent.getValue();
9590            if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
9591                st.endSample();
9592                numWakelocksSetStale++;
9593            }
9594        }
9595
9596        // Record whether we've seen a non-zero time (for debugging b/22716723).
9597        if (wakelockStats.isEmpty()) {
9598            Slog.wtf(TAG, "All kernel wakelocks had time of zero");
9599        }
9600
9601        if (numWakelocksSetStale == mKernelWakelockStats.size()) {
9602            Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
9603                    wakelockStats.kernelWakelockVersion);
9604        }
9605    }
9606
9607    // We use an anonymous class to access these variables,
9608    // so they can't live on the stack or they'd have to be
9609    // final MutableLong objects (more allocations).
9610    // Used in updateCpuTimeLocked().
9611    long mTempTotalCpuUserTimeUs;
9612    long mTempTotalCpuSystemTimeUs;
9613
9614    /**
9615     * Reads the newest memory stats from the kernel.
9616     */
9617    public void updateKernelMemoryBandwidthLocked() {
9618        mKernelMemoryBandwidthStats.updateStats();
9619        LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries();
9620        final int bandwidthEntryCount = bandwidthEntries.size();
9621        int index;
9622        for (int i = 0; i < bandwidthEntryCount; i++) {
9623            SamplingTimer timer;
9624            if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) {
9625                timer = mKernelMemoryStats.valueAt(index);
9626            } else {
9627                timer = new SamplingTimer(mClocks, mOnBatteryTimeBase);
9628                mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer);
9629            }
9630            timer.update(bandwidthEntries.valueAt(i), 1);
9631            if (DEBUG_MEMORY) {
9632                Slog.d(TAG, String.format("Added entry %d and updated timer to: "
9633                        + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i),
9634                        mKernelMemoryStats.get(
9635                                bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime,
9636                        mKernelMemoryStats.size()));
9637            }
9638        }
9639    }
9640
9641    /**
9642     * Read and distribute CPU usage across apps. If their are partial wakelocks being held
9643     * and we are on battery with screen off, we give more of the cpu time to those apps holding
9644     * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
9645     */
9646    public void updateCpuTimeLocked() {
9647        if (mPowerProfile == null) {
9648            return;
9649        }
9650
9651        if (DEBUG_ENERGY_CPU) {
9652            Slog.d(TAG, "!Cpu updating!");
9653        }
9654
9655        // Holding a wakelock costs more than just using the cpu.
9656        // Currently, we assign only half the cpu time to an app that is running but
9657        // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
9658        // If no app is holding a wakelock, then the distribution is normal.
9659        final int wakelockWeight = 50;
9660
9661        // Read the time spent for each cluster at various cpu frequencies.
9662        final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
9663        for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
9664            clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
9665        }
9666
9667        int numWakelocks = 0;
9668
9669        // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
9670        // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
9671        final int numPartialTimers = mPartialTimers.size();
9672        if (mOnBatteryScreenOffTimeBase.isRunning()) {
9673            for (int i = 0; i < numPartialTimers; i++) {
9674                final StopwatchTimer timer = mPartialTimers.get(i);
9675                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
9676                    // Since the collection and blaming of wakelocks can be scheduled to run after
9677                    // some delay, the mPartialTimers list may have new entries. We can't blame
9678                    // the newly added timer for past cpu time, so we only consider timers that
9679                    // were present for one round of collection. Once a timer has gone through
9680                    // a round of collection, its mInList field is set to true.
9681                    numWakelocks++;
9682                }
9683            }
9684        }
9685
9686        final int numWakelocksF = numWakelocks;
9687        mTempTotalCpuUserTimeUs = 0;
9688        mTempTotalCpuSystemTimeUs = 0;
9689
9690        // Read the CPU data for each UID. This will internally generate a snapshot so next time
9691        // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
9692        // we just ignore the data.
9693        final long startTimeMs = mClocks.elapsedRealtime();
9694        mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
9695                new KernelUidCpuTimeReader.Callback() {
9696                    @Override
9697                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
9698                        final Uid u = getUidStatsLocked(mapUid(uid));
9699
9700                        // Accumulate the total system and user time.
9701                        mTempTotalCpuUserTimeUs += userTimeUs;
9702                        mTempTotalCpuSystemTimeUs += systemTimeUs;
9703
9704                        StringBuilder sb = null;
9705                        if (DEBUG_ENERGY_CPU) {
9706                            sb = new StringBuilder();
9707                            sb.append("  got time for uid=").append(u.mUid).append(": u=");
9708                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
9709                            sb.append(" s=");
9710                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
9711                            sb.append("\n");
9712                        }
9713
9714                        if (numWakelocksF > 0) {
9715                            // We have wakelocks being held, so only give a portion of the
9716                            // time to the process. The rest will be distributed among wakelock
9717                            // holders.
9718                            userTimeUs = (userTimeUs * wakelockWeight) / 100;
9719                            systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
9720                        }
9721
9722                        if (sb != null) {
9723                            sb.append("  adding to uid=").append(u.mUid).append(": u=");
9724                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
9725                            sb.append(" s=");
9726                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
9727                            Slog.d(TAG, sb.toString());
9728                        }
9729
9730                        u.mUserCpuTime.addCountLocked(userTimeUs);
9731                        u.mSystemCpuTime.addCountLocked(systemTimeUs);
9732
9733                        // Add the cpu speeds to this UID. These are used as a ratio
9734                        // for computing the power this UID used.
9735                        final int numClusters = mPowerProfile.getNumCpuClusters();
9736                        if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
9737                                numClusters) {
9738                            u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
9739                        }
9740
9741                        for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
9742                            final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(
9743                                    cluster);
9744                            if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
9745                                    u.mCpuClusterSpeed[cluster].length) {
9746                                u.mCpuClusterSpeed[cluster] =
9747                                        new LongSamplingCounter[speedsInCluster];
9748                            }
9749
9750                            final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
9751                            for (int speed = 0; speed < clusterSpeeds[cluster].length; speed++) {
9752                                if (cpuSpeeds[speed] == null) {
9753                                    cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
9754                                }
9755                                cpuSpeeds[speed].addCountLocked(clusterSpeeds[cluster][speed]);
9756                            }
9757                        }
9758                    }
9759                });
9760
9761        // TODO: STOPSHIP, remove the "true" below after b/34961340 is fixed
9762        if (DEBUG_ENERGY_CPU || true) {
9763            Slog.d(TAG, "Reading cpu stats took " + (mClocks.elapsedRealtime() - startTimeMs) +
9764                    " ms");
9765        }
9766
9767        if (mOnBatteryInternal && numWakelocks > 0) {
9768            // Distribute a portion of the total cpu time to wakelock holders.
9769            mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
9770            mTempTotalCpuSystemTimeUs =
9771                    (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
9772
9773            for (int i = 0; i < numPartialTimers; i++) {
9774                final StopwatchTimer timer = mPartialTimers.get(i);
9775
9776                // The system does not share any blame, as it is usually holding the wakelock
9777                // on behalf of an app.
9778                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
9779                    int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
9780                    int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
9781
9782                    if (DEBUG_ENERGY_CPU) {
9783                        StringBuilder sb = new StringBuilder();
9784                        sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
9785                                .append(": u=");
9786                        TimeUtils.formatDuration(userTimeUs / 1000, sb);
9787                        sb.append(" s=");
9788                        TimeUtils.formatDuration(systemTimeUs / 1000, sb);
9789                        Slog.d(TAG, sb.toString());
9790                    }
9791
9792                    timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
9793                    timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
9794
9795                    final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
9796                    proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
9797
9798                    mTempTotalCpuUserTimeUs -= userTimeUs;
9799                    mTempTotalCpuSystemTimeUs -= systemTimeUs;
9800                    numWakelocks--;
9801                }
9802            }
9803
9804            if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
9805                // Anything left over is given to the system.
9806                if (DEBUG_ENERGY_CPU) {
9807                    StringBuilder sb = new StringBuilder();
9808                    sb.append("  Distributing lost time to system: u=");
9809                    TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
9810                    sb.append(" s=");
9811                    TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
9812                    Slog.d(TAG, sb.toString());
9813                }
9814
9815                final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
9816                u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
9817                u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
9818
9819                final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
9820                proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000,
9821                        (int) mTempTotalCpuSystemTimeUs / 1000);
9822            }
9823        }
9824
9825        // See if there is a difference in wakelocks between this collection and the last
9826        // collection.
9827        if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
9828            // No difference, so each timer is now considered for the next collection.
9829            for (int i = 0; i < numPartialTimers; i++) {
9830                mPartialTimers.get(i).mInList = true;
9831            }
9832        } else {
9833            // The lists are different, meaning we added (or removed a timer) since the last
9834            // collection.
9835            final int numLastPartialTimers = mLastPartialTimers.size();
9836            for (int i = 0; i < numLastPartialTimers; i++) {
9837                mLastPartialTimers.get(i).mInList = false;
9838            }
9839            mLastPartialTimers.clear();
9840
9841            // Mark the current timers as gone through a collection.
9842            for (int i = 0; i < numPartialTimers; i++) {
9843                final StopwatchTimer timer = mPartialTimers.get(i);
9844                timer.mInList = true;
9845                mLastPartialTimers.add(timer);
9846            }
9847        }
9848    }
9849
9850    boolean setChargingLocked(boolean charging) {
9851        if (mCharging != charging) {
9852            mCharging = charging;
9853            if (charging) {
9854                mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
9855            } else {
9856                mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
9857            }
9858            mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
9859            return true;
9860        }
9861        return false;
9862    }
9863
9864    void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
9865            final int oldStatus, final int level, final int chargeUAh) {
9866        boolean doWrite = false;
9867        Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
9868        m.arg1 = onBattery ? 1 : 0;
9869        mHandler.sendMessage(m);
9870
9871        final long uptime = mSecUptime * 1000;
9872        final long realtime = mSecRealtime * 1000;
9873        final boolean screenOn = mScreenState == Display.STATE_ON;
9874        if (onBattery) {
9875            // We will reset our status if we are unplugging after the
9876            // battery was last full, or the level is at 100, or
9877            // we have gone through a significant charge (from a very low
9878            // level to a now very high level).
9879            boolean reset = false;
9880            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
9881                    || level >= 90
9882                    || (mDischargeCurrentLevel < 20 && level >= 80)
9883                    || (getHighDischargeAmountSinceCharge() >= 200
9884                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
9885                Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
9886                        + " dischargeLevel=" + mDischargeCurrentLevel
9887                        + " lowAmount=" + getLowDischargeAmountSinceCharge()
9888                        + " highAmount=" + getHighDischargeAmountSinceCharge());
9889                // Before we write, collect a snapshot of the final aggregated
9890                // stats to be reported in the next checkin.  Only do this if we have
9891                // a sufficient amount of data to make it interesting.
9892                if (getLowDischargeAmountSinceCharge() >= 20) {
9893                    final Parcel parcel = Parcel.obtain();
9894                    writeSummaryToParcel(parcel, true);
9895                    BackgroundThread.getHandler().post(new Runnable() {
9896                        @Override public void run() {
9897                            synchronized (mCheckinFile) {
9898                                FileOutputStream stream = null;
9899                                try {
9900                                    stream = mCheckinFile.startWrite();
9901                                    stream.write(parcel.marshall());
9902                                    stream.flush();
9903                                    FileUtils.sync(stream);
9904                                    stream.close();
9905                                    mCheckinFile.finishWrite(stream);
9906                                } catch (IOException e) {
9907                                    Slog.w("BatteryStats",
9908                                            "Error writing checkin battery statistics", e);
9909                                    mCheckinFile.failWrite(stream);
9910                                } finally {
9911                                    parcel.recycle();
9912                                }
9913                            }
9914                        }
9915                    });
9916                }
9917                doWrite = true;
9918                resetAllStatsLocked();
9919                if (chargeUAh > 0 && level > 0) {
9920                    // Only use the reported coulomb charge value if it is supported and reported.
9921                    mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
9922                }
9923                mDischargeStartLevel = level;
9924                reset = true;
9925                mDischargeStepTracker.init();
9926            }
9927            if (mCharging) {
9928                setChargingLocked(false);
9929            }
9930            mLastChargingStateLevel = level;
9931            mOnBattery = mOnBatteryInternal = true;
9932            mLastDischargeStepLevel = level;
9933            mMinDischargeStepLevel = level;
9934            mDischargeStepTracker.clearTime();
9935            mDailyDischargeStepTracker.clearTime();
9936            mInitStepMode = mCurStepMode;
9937            mModStepMode = 0;
9938            pullPendingStateUpdatesLocked();
9939            mHistoryCur.batteryLevel = (byte)level;
9940            mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
9941            if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
9942                    + Integer.toHexString(mHistoryCur.states));
9943            if (reset) {
9944                mRecordingHistory = true;
9945                startRecordingHistory(mSecRealtime, mSecUptime, reset);
9946            }
9947            addHistoryRecordLocked(mSecRealtime, mSecUptime);
9948            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
9949            if (screenOn) {
9950                mDischargeScreenOnUnplugLevel = level;
9951                mDischargeScreenOffUnplugLevel = 0;
9952            } else {
9953                mDischargeScreenOnUnplugLevel = 0;
9954                mDischargeScreenOffUnplugLevel = level;
9955            }
9956            mDischargeAmountScreenOn = 0;
9957            mDischargeAmountScreenOff = 0;
9958            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
9959        } else {
9960            mLastChargingStateLevel = level;
9961            mOnBattery = mOnBatteryInternal = false;
9962            pullPendingStateUpdatesLocked();
9963            mHistoryCur.batteryLevel = (byte)level;
9964            mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
9965            if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
9966                    + Integer.toHexString(mHistoryCur.states));
9967            addHistoryRecordLocked(mSecRealtime, mSecUptime);
9968            mDischargeCurrentLevel = mDischargePlugLevel = level;
9969            if (level < mDischargeUnplugLevel) {
9970                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
9971                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
9972            }
9973            updateDischargeScreenLevelsLocked(screenOn, screenOn);
9974            updateTimeBasesLocked(false, !screenOn, uptime, realtime);
9975            mChargeStepTracker.init();
9976            mLastChargeStepLevel = level;
9977            mMaxChargeStepLevel = level;
9978            mInitStepMode = mCurStepMode;
9979            mModStepMode = 0;
9980        }
9981        if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
9982            if (mFile != null) {
9983                writeAsyncLocked();
9984            }
9985        }
9986    }
9987
9988    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
9989            boolean reset) {
9990        mRecordingHistory = true;
9991        mHistoryCur.currentTime = System.currentTimeMillis();
9992        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
9993                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
9994                mHistoryCur);
9995        mHistoryCur.currentTime = 0;
9996        if (reset) {
9997            initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
9998        }
9999    }
10000
10001    private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
10002            final long uptimeMs) {
10003        if (mRecordingHistory) {
10004            mHistoryCur.currentTime = currentTime;
10005            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
10006                    mHistoryCur);
10007            mHistoryCur.currentTime = 0;
10008        }
10009    }
10010
10011    private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
10012        if (mRecordingHistory) {
10013            mHistoryCur.currentTime = System.currentTimeMillis();
10014            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
10015                    mHistoryCur);
10016            mHistoryCur.currentTime = 0;
10017        }
10018    }
10019
10020    private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
10021        if (mExternalSync != null) {
10022            mExternalSync.scheduleSync(reason, updateFlags);
10023        }
10024    }
10025
10026    // This should probably be exposed in the API, though it's not critical
10027    public static final int BATTERY_PLUGGED_NONE = 0;
10028
10029    public void setBatteryStateLocked(int status, int health, int plugType, int level,
10030            int temp, int volt, int chargeUAh, int chargeFullUAh) {
10031        // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
10032        temp = Math.max(0, temp);
10033
10034        final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
10035        final long uptime = mClocks.uptimeMillis();
10036        final long elapsedRealtime = mClocks.elapsedRealtime();
10037        if (!mHaveBatteryLevel) {
10038            mHaveBatteryLevel = true;
10039            // We start out assuming that the device is plugged in (not
10040            // on battery).  If our first report is now that we are indeed
10041            // plugged in, then twiddle our state to correctly reflect that
10042            // since we won't be going through the full setOnBattery().
10043            if (onBattery == mOnBattery) {
10044                if (onBattery) {
10045                    mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
10046                } else {
10047                    mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
10048                }
10049            }
10050            // Always start out assuming charging, that will be updated later.
10051            mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
10052            mHistoryCur.batteryStatus = (byte)status;
10053            mHistoryCur.batteryLevel = (byte)level;
10054            mHistoryCur.batteryChargeUAh = chargeUAh;
10055            mMaxChargeStepLevel = mMinDischargeStepLevel =
10056                    mLastChargeStepLevel = mLastDischargeStepLevel = level;
10057            mLastChargingStateLevel = level;
10058        } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
10059            recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
10060        }
10061        int oldStatus = mHistoryCur.batteryStatus;
10062        if (onBattery) {
10063            mDischargeCurrentLevel = level;
10064            if (!mRecordingHistory) {
10065                mRecordingHistory = true;
10066                startRecordingHistory(elapsedRealtime, uptime, true);
10067            }
10068        } else if (level < 96) {
10069            if (!mRecordingHistory) {
10070                mRecordingHistory = true;
10071                startRecordingHistory(elapsedRealtime, uptime, true);
10072            }
10073        }
10074        mCurrentBatteryLevel = level;
10075        if (mDischargePlugLevel < 0) {
10076            mDischargePlugLevel = level;
10077        }
10078
10079        if (onBattery != mOnBattery) {
10080            mHistoryCur.batteryLevel = (byte)level;
10081            mHistoryCur.batteryStatus = (byte)status;
10082            mHistoryCur.batteryHealth = (byte)health;
10083            mHistoryCur.batteryPlugType = (byte)plugType;
10084            mHistoryCur.batteryTemperature = (short)temp;
10085            mHistoryCur.batteryVoltage = (char)volt;
10086            if (chargeUAh < mHistoryCur.batteryChargeUAh) {
10087                // Only record discharges
10088                final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
10089                mDischargeCounter.addCountLocked(chargeDiff);
10090                mDischargeScreenOffCounter.addCountLocked(chargeDiff);
10091            }
10092            mHistoryCur.batteryChargeUAh = chargeUAh;
10093            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
10094        } else {
10095            boolean changed = false;
10096            if (mHistoryCur.batteryLevel != level) {
10097                mHistoryCur.batteryLevel = (byte)level;
10098                changed = true;
10099
10100                // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
10101                // which will pull external stats.
10102                scheduleSyncExternalStatsLocked("battery-level", ExternalStatsSync.UPDATE_ALL);
10103            }
10104            if (mHistoryCur.batteryStatus != status) {
10105                mHistoryCur.batteryStatus = (byte)status;
10106                changed = true;
10107            }
10108            if (mHistoryCur.batteryHealth != health) {
10109                mHistoryCur.batteryHealth = (byte)health;
10110                changed = true;
10111            }
10112            if (mHistoryCur.batteryPlugType != plugType) {
10113                mHistoryCur.batteryPlugType = (byte)plugType;
10114                changed = true;
10115            }
10116            if (temp >= (mHistoryCur.batteryTemperature+10)
10117                    || temp <= (mHistoryCur.batteryTemperature-10)) {
10118                mHistoryCur.batteryTemperature = (short)temp;
10119                changed = true;
10120            }
10121            if (volt > (mHistoryCur.batteryVoltage+20)
10122                    || volt < (mHistoryCur.batteryVoltage-20)) {
10123                mHistoryCur.batteryVoltage = (char)volt;
10124                changed = true;
10125            }
10126            if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
10127                    || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
10128                if (chargeUAh < mHistoryCur.batteryChargeUAh) {
10129                    // Only record discharges
10130                    final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
10131                    mDischargeCounter.addCountLocked(chargeDiff);
10132                    mDischargeScreenOffCounter.addCountLocked(chargeDiff);
10133                }
10134                mHistoryCur.batteryChargeUAh = chargeUAh;
10135                changed = true;
10136            }
10137            long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
10138                    | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
10139                    | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
10140            if (onBattery) {
10141                changed |= setChargingLocked(false);
10142                if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
10143                    mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
10144                            modeBits, elapsedRealtime);
10145                    mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
10146                            modeBits, elapsedRealtime);
10147                    mLastDischargeStepLevel = level;
10148                    mMinDischargeStepLevel = level;
10149                    mInitStepMode = mCurStepMode;
10150                    mModStepMode = 0;
10151                }
10152            } else {
10153                if (level >= 90) {
10154                    // If the battery level is at least 90%, always consider the device to be
10155                    // charging even if it happens to go down a level.
10156                    changed |= setChargingLocked(true);
10157                    mLastChargeStepLevel = level;
10158                } if (!mCharging) {
10159                    if (mLastChargeStepLevel < level) {
10160                        // We have not reporting that we are charging, but the level has now
10161                        // gone up, so consider the state to be charging.
10162                        changed |= setChargingLocked(true);
10163                        mLastChargeStepLevel = level;
10164                    }
10165                } else {
10166                    if (mLastChargeStepLevel > level) {
10167                        // We had reported that the device was charging, but here we are with
10168                        // power connected and the level going down.  Looks like the current
10169                        // power supplied isn't enough, so consider the device to now be
10170                        // discharging.
10171                        changed |= setChargingLocked(false);
10172                        mLastChargeStepLevel = level;
10173                    }
10174                }
10175                if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
10176                    mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
10177                            modeBits, elapsedRealtime);
10178                    mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
10179                            modeBits, elapsedRealtime);
10180                    mLastChargeStepLevel = level;
10181                    mMaxChargeStepLevel = level;
10182                    mInitStepMode = mCurStepMode;
10183                    mModStepMode = 0;
10184                }
10185            }
10186            if (changed) {
10187                addHistoryRecordLocked(elapsedRealtime, uptime);
10188            }
10189        }
10190        if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
10191            // We don't record history while we are plugged in and fully charged.
10192            // The next time we are unplugged, history will be cleared.
10193            mRecordingHistory = DEBUG;
10194        }
10195
10196        if (differsByMoreThan(chargeFullUAh, mLastChargeFullUAh, 100)) {
10197            mLastChargeFullUAh = chargeFullUAh;
10198            addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ESTIMATED_BATTERY_CAP,
10199                    "", chargeFullUAh / 1000);
10200        }
10201    }
10202
10203    private static boolean differsByMoreThan(int left, int right, int diff) {
10204        return Math.abs(left - right) > diff;
10205    }
10206
10207    public long getAwakeTimeBattery() {
10208        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
10209    }
10210
10211    public long getAwakeTimePlugged() {
10212        return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
10213    }
10214
10215    @Override
10216    public long computeUptime(long curTime, int which) {
10217        switch (which) {
10218            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
10219            case STATS_CURRENT: return (curTime-mUptimeStart);
10220            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
10221        }
10222        return 0;
10223    }
10224
10225    @Override
10226    public long computeRealtime(long curTime, int which) {
10227        switch (which) {
10228            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
10229            case STATS_CURRENT: return (curTime-mRealtimeStart);
10230            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
10231        }
10232        return 0;
10233    }
10234
10235    @Override
10236    public long computeBatteryUptime(long curTime, int which) {
10237        return mOnBatteryTimeBase.computeUptime(curTime, which);
10238    }
10239
10240    @Override
10241    public long computeBatteryRealtime(long curTime, int which) {
10242        return mOnBatteryTimeBase.computeRealtime(curTime, which);
10243    }
10244
10245    @Override
10246    public long computeBatteryScreenOffUptime(long curTime, int which) {
10247        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
10248    }
10249
10250    @Override
10251    public long computeBatteryScreenOffRealtime(long curTime, int which) {
10252        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
10253    }
10254
10255    private long computeTimePerLevel(long[] steps, int numSteps) {
10256        // For now we'll do a simple average across all steps.
10257        if (numSteps <= 0) {
10258            return -1;
10259        }
10260        long total = 0;
10261        for (int i=0; i<numSteps; i++) {
10262            total += steps[i] & STEP_LEVEL_TIME_MASK;
10263        }
10264        return total / numSteps;
10265        /*
10266        long[] buckets = new long[numSteps];
10267        int numBuckets = 0;
10268        int numToAverage = 4;
10269        int i = 0;
10270        while (i < numSteps) {
10271            long totalTime = 0;
10272            int num = 0;
10273            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
10274                totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
10275                num++;
10276            }
10277            buckets[numBuckets] = totalTime / num;
10278            numBuckets++;
10279            numToAverage *= 2;
10280            i += num;
10281        }
10282        if (numBuckets < 1) {
10283            return -1;
10284        }
10285        long averageTime = buckets[numBuckets-1];
10286        for (i=numBuckets-2; i>=0; i--) {
10287            averageTime = (averageTime + buckets[i]) / 2;
10288        }
10289        return averageTime;
10290        */
10291    }
10292
10293    @Override
10294    public long computeBatteryTimeRemaining(long curTime) {
10295        if (!mOnBattery) {
10296            return -1;
10297        }
10298        /* Simple implementation just looks at the average discharge per level across the
10299           entire sample period.
10300        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
10301        if (discharge < 2) {
10302            return -1;
10303        }
10304        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
10305        if (duration < 1000*1000) {
10306            return -1;
10307        }
10308        long usPerLevel = duration/discharge;
10309        return usPerLevel * mCurrentBatteryLevel;
10310        */
10311        if (mDischargeStepTracker.mNumStepDurations < 1) {
10312            return -1;
10313        }
10314        long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
10315        if (msPerLevel <= 0) {
10316            return -1;
10317        }
10318        return (msPerLevel * mCurrentBatteryLevel) * 1000;
10319    }
10320
10321    @Override
10322    public LevelStepTracker getDischargeLevelStepTracker() {
10323        return mDischargeStepTracker;
10324    }
10325
10326    @Override
10327    public LevelStepTracker getDailyDischargeLevelStepTracker() {
10328        return mDailyDischargeStepTracker;
10329    }
10330
10331    @Override
10332    public long computeChargeTimeRemaining(long curTime) {
10333        if (mOnBattery) {
10334            // Not yet working.
10335            return -1;
10336        }
10337        /* Broken
10338        int curLevel = mCurrentBatteryLevel;
10339        int plugLevel = mDischargePlugLevel;
10340        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
10341            return -1;
10342        }
10343        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
10344        if (duration < 1000*1000) {
10345            return -1;
10346        }
10347        long usPerLevel = duration/(curLevel-plugLevel);
10348        return usPerLevel * (100-curLevel);
10349        */
10350        if (mChargeStepTracker.mNumStepDurations < 1) {
10351            return -1;
10352        }
10353        long msPerLevel = mChargeStepTracker.computeTimePerLevel();
10354        if (msPerLevel <= 0) {
10355            return -1;
10356        }
10357        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
10358    }
10359
10360    @Override
10361    public LevelStepTracker getChargeLevelStepTracker() {
10362        return mChargeStepTracker;
10363    }
10364
10365    @Override
10366    public LevelStepTracker getDailyChargeLevelStepTracker() {
10367        return mDailyChargeStepTracker;
10368    }
10369
10370    @Override
10371    public ArrayList<PackageChange> getDailyPackageChanges() {
10372        return mDailyPackageChanges;
10373    }
10374
10375    protected long getBatteryUptimeLocked() {
10376        return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
10377    }
10378
10379    @Override
10380    public long getBatteryUptime(long curTime) {
10381        return mOnBatteryTimeBase.getUptime(curTime);
10382    }
10383
10384    @Override
10385    public long getBatteryRealtime(long curTime) {
10386        return mOnBatteryTimeBase.getRealtime(curTime);
10387    }
10388
10389    @Override
10390    public int getDischargeStartLevel() {
10391        synchronized(this) {
10392            return getDischargeStartLevelLocked();
10393        }
10394    }
10395
10396    public int getDischargeStartLevelLocked() {
10397            return mDischargeUnplugLevel;
10398    }
10399
10400    @Override
10401    public int getDischargeCurrentLevel() {
10402        synchronized(this) {
10403            return getDischargeCurrentLevelLocked();
10404        }
10405    }
10406
10407    public int getDischargeCurrentLevelLocked() {
10408        return mDischargeCurrentLevel;
10409    }
10410
10411    @Override
10412    public int getLowDischargeAmountSinceCharge() {
10413        synchronized(this) {
10414            int val = mLowDischargeAmountSinceCharge;
10415            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
10416                val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
10417            }
10418            return val;
10419        }
10420    }
10421
10422    @Override
10423    public int getHighDischargeAmountSinceCharge() {
10424        synchronized(this) {
10425            int val = mHighDischargeAmountSinceCharge;
10426            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
10427                val += mDischargeUnplugLevel-mDischargeCurrentLevel;
10428            }
10429            return val;
10430        }
10431    }
10432
10433    @Override
10434    public int getDischargeAmount(int which) {
10435        int dischargeAmount = which == STATS_SINCE_CHARGED
10436                ? getHighDischargeAmountSinceCharge()
10437                : (getDischargeStartLevel() - getDischargeCurrentLevel());
10438        if (dischargeAmount < 0) {
10439            dischargeAmount = 0;
10440        }
10441        return dischargeAmount;
10442    }
10443
10444    public int getDischargeAmountScreenOn() {
10445        synchronized(this) {
10446            int val = mDischargeAmountScreenOn;
10447            if (mOnBattery && mScreenState == Display.STATE_ON
10448                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
10449                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
10450            }
10451            return val;
10452        }
10453    }
10454
10455    public int getDischargeAmountScreenOnSinceCharge() {
10456        synchronized(this) {
10457            int val = mDischargeAmountScreenOnSinceCharge;
10458            if (mOnBattery && mScreenState == Display.STATE_ON
10459                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
10460                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
10461            }
10462            return val;
10463        }
10464    }
10465
10466    public int getDischargeAmountScreenOff() {
10467        synchronized(this) {
10468            int val = mDischargeAmountScreenOff;
10469            if (mOnBattery && mScreenState != Display.STATE_ON
10470                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
10471                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
10472            }
10473            return val;
10474        }
10475    }
10476
10477    public int getDischargeAmountScreenOffSinceCharge() {
10478        synchronized(this) {
10479            int val = mDischargeAmountScreenOffSinceCharge;
10480            if (mOnBattery && mScreenState != Display.STATE_ON
10481                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
10482                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
10483            }
10484            return val;
10485        }
10486    }
10487
10488    /**
10489     * Retrieve the statistics object for a particular uid, creating if needed.
10490     */
10491    public Uid getUidStatsLocked(int uid) {
10492        Uid u = mUidStats.get(uid);
10493        if (u == null) {
10494            u = new Uid(this, uid);
10495            mUidStats.put(uid, u);
10496        }
10497        return u;
10498    }
10499
10500    /**
10501     * Remove the statistics object for a particular uid.
10502     */
10503    public void removeUidStatsLocked(int uid) {
10504        mKernelUidCpuTimeReader.removeUid(uid);
10505        mUidStats.remove(uid);
10506    }
10507
10508    /**
10509     * Retrieve the statistics object for a particular process, creating
10510     * if needed.
10511     */
10512    public Uid.Proc getProcessStatsLocked(int uid, String name) {
10513        uid = mapUid(uid);
10514        Uid u = getUidStatsLocked(uid);
10515        return u.getProcessStatsLocked(name);
10516    }
10517
10518    /**
10519     * Retrieve the statistics object for a particular process, creating
10520     * if needed.
10521     */
10522    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
10523        uid = mapUid(uid);
10524        Uid u = getUidStatsLocked(uid);
10525        return u.getPackageStatsLocked(pkg);
10526    }
10527
10528    /**
10529     * Retrieve the statistics object for a particular service, creating
10530     * if needed.
10531     */
10532    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
10533        uid = mapUid(uid);
10534        Uid u = getUidStatsLocked(uid);
10535        return u.getServiceStatsLocked(pkg, name);
10536    }
10537
10538    public void shutdownLocked() {
10539        recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
10540        writeSyncLocked();
10541        mShuttingDown = true;
10542    }
10543
10544    Parcel mPendingWrite = null;
10545    final ReentrantLock mWriteLock = new ReentrantLock();
10546
10547    public void writeAsyncLocked() {
10548        writeLocked(false);
10549    }
10550
10551    public void writeSyncLocked() {
10552        writeLocked(true);
10553    }
10554
10555    void writeLocked(boolean sync) {
10556        if (mFile == null) {
10557            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
10558            return;
10559        }
10560
10561        if (mShuttingDown) {
10562            return;
10563        }
10564
10565        Parcel out = Parcel.obtain();
10566        writeSummaryToParcel(out, true);
10567        mLastWriteTime = mClocks.elapsedRealtime();
10568
10569        if (mPendingWrite != null) {
10570            mPendingWrite.recycle();
10571        }
10572        mPendingWrite = out;
10573
10574        if (sync) {
10575            commitPendingDataToDisk();
10576        } else {
10577            BackgroundThread.getHandler().post(new Runnable() {
10578                @Override public void run() {
10579                    commitPendingDataToDisk();
10580                }
10581            });
10582        }
10583    }
10584
10585    public void commitPendingDataToDisk() {
10586        final Parcel next;
10587        synchronized (this) {
10588            next = mPendingWrite;
10589            mPendingWrite = null;
10590            if (next == null) {
10591                return;
10592            }
10593        }
10594
10595        mWriteLock.lock();
10596        try {
10597            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
10598            stream.write(next.marshall());
10599            stream.flush();
10600            FileUtils.sync(stream);
10601            stream.close();
10602            mFile.commit();
10603        } catch (IOException e) {
10604            Slog.w("BatteryStats", "Error writing battery statistics", e);
10605            mFile.rollback();
10606        } finally {
10607            next.recycle();
10608            mWriteLock.unlock();
10609        }
10610    }
10611
10612    public void readLocked() {
10613        if (mDailyFile != null) {
10614            readDailyStatsLocked();
10615        }
10616
10617        if (mFile == null) {
10618            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
10619            return;
10620        }
10621
10622        mUidStats.clear();
10623
10624        try {
10625            File file = mFile.chooseForRead();
10626            if (!file.exists()) {
10627                return;
10628            }
10629            FileInputStream stream = new FileInputStream(file);
10630
10631            byte[] raw = BatteryStatsHelper.readFully(stream);
10632            Parcel in = Parcel.obtain();
10633            in.unmarshall(raw, 0, raw.length);
10634            in.setDataPosition(0);
10635            stream.close();
10636
10637            readSummaryFromParcel(in);
10638        } catch(Exception e) {
10639            Slog.e("BatteryStats", "Error reading battery statistics", e);
10640            resetAllStatsLocked();
10641        }
10642
10643        mEndPlatformVersion = Build.ID;
10644
10645        if (mHistoryBuffer.dataPosition() > 0) {
10646            mRecordingHistory = true;
10647            final long elapsedRealtime = mClocks.elapsedRealtime();
10648            final long uptime = mClocks.uptimeMillis();
10649            if (USE_OLD_HISTORY) {
10650                addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
10651            }
10652            addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
10653            startRecordingHistory(elapsedRealtime, uptime, false);
10654        }
10655
10656        recordDailyStatsIfNeededLocked(false);
10657    }
10658
10659    public int describeContents() {
10660        return 0;
10661    }
10662
10663    void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
10664        final long historyBaseTime = in.readLong();
10665
10666        mHistoryBuffer.setDataSize(0);
10667        mHistoryBuffer.setDataPosition(0);
10668        mHistoryTagPool.clear();
10669        mNextHistoryTagIdx = 0;
10670        mNumHistoryTagChars = 0;
10671
10672        int numTags = in.readInt();
10673        for (int i=0; i<numTags; i++) {
10674            int idx = in.readInt();
10675            String str = in.readString();
10676            if (str == null) {
10677                throw new ParcelFormatException("null history tag string");
10678            }
10679            int uid = in.readInt();
10680            HistoryTag tag = new HistoryTag();
10681            tag.string = str;
10682            tag.uid = uid;
10683            tag.poolIdx = idx;
10684            mHistoryTagPool.put(tag, idx);
10685            if (idx >= mNextHistoryTagIdx) {
10686                mNextHistoryTagIdx = idx+1;
10687            }
10688            mNumHistoryTagChars += tag.string.length() + 1;
10689        }
10690
10691        int bufSize = in.readInt();
10692        int curPos = in.dataPosition();
10693        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
10694            throw new ParcelFormatException("File corrupt: history data buffer too large " +
10695                    bufSize);
10696        } else if ((bufSize&~3) != bufSize) {
10697            throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
10698                    bufSize);
10699        } else {
10700            if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
10701                    + " bytes at " + curPos);
10702            mHistoryBuffer.appendFrom(in, curPos, bufSize);
10703            in.setDataPosition(curPos + bufSize);
10704        }
10705
10706        if (andOldHistory) {
10707            readOldHistory(in);
10708        }
10709
10710        if (DEBUG_HISTORY) {
10711            StringBuilder sb = new StringBuilder(128);
10712            sb.append("****************** OLD mHistoryBaseTime: ");
10713            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10714            Slog.i(TAG, sb.toString());
10715        }
10716        mHistoryBaseTime = historyBaseTime;
10717        if (DEBUG_HISTORY) {
10718            StringBuilder sb = new StringBuilder(128);
10719            sb.append("****************** NEW mHistoryBaseTime: ");
10720            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10721            Slog.i(TAG, sb.toString());
10722        }
10723
10724        // We are just arbitrarily going to insert 1 minute from the sample of
10725        // the last run until samples in this run.
10726        if (mHistoryBaseTime > 0) {
10727            long oldnow = mClocks.elapsedRealtime();
10728            mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
10729            if (DEBUG_HISTORY) {
10730                StringBuilder sb = new StringBuilder(128);
10731                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
10732                TimeUtils.formatDuration(mHistoryBaseTime, sb);
10733                Slog.i(TAG, sb.toString());
10734            }
10735        }
10736    }
10737
10738    void readOldHistory(Parcel in) {
10739        if (!USE_OLD_HISTORY) {
10740            return;
10741        }
10742        mHistory = mHistoryEnd = mHistoryCache = null;
10743        long time;
10744        while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
10745            HistoryItem rec = new HistoryItem(time, in);
10746            addHistoryRecordLocked(rec);
10747        }
10748    }
10749
10750    void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
10751        if (DEBUG_HISTORY) {
10752            StringBuilder sb = new StringBuilder(128);
10753            sb.append("****************** WRITING mHistoryBaseTime: ");
10754            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10755            sb.append(" mLastHistoryElapsedRealtime: ");
10756            TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
10757            Slog.i(TAG, sb.toString());
10758        }
10759        out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
10760        if (!inclData) {
10761            out.writeInt(0);
10762            out.writeInt(0);
10763            return;
10764        }
10765        out.writeInt(mHistoryTagPool.size());
10766        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10767            HistoryTag tag = ent.getKey();
10768            out.writeInt(ent.getValue());
10769            out.writeString(tag.string);
10770            out.writeInt(tag.uid);
10771        }
10772        out.writeInt(mHistoryBuffer.dataSize());
10773        if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
10774                + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
10775        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
10776
10777        if (andOldHistory) {
10778            writeOldHistory(out);
10779        }
10780    }
10781
10782    void writeOldHistory(Parcel out) {
10783        if (!USE_OLD_HISTORY) {
10784            return;
10785        }
10786        HistoryItem rec = mHistory;
10787        while (rec != null) {
10788            if (rec.time >= 0) rec.writeToParcel(out, 0);
10789            rec = rec.next;
10790        }
10791        out.writeLong(-1);
10792    }
10793
10794    public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
10795        final int version = in.readInt();
10796        if (version != VERSION) {
10797            Slog.w("BatteryStats", "readFromParcel: version got " + version
10798                + ", expected " + VERSION + "; erasing old stats");
10799            return;
10800        }
10801
10802        readHistory(in, true);
10803
10804        mStartCount = in.readInt();
10805        mUptime = in.readLong();
10806        mRealtime = in.readLong();
10807        mStartClockTime = in.readLong();
10808        mStartPlatformVersion = in.readString();
10809        mEndPlatformVersion = in.readString();
10810        mOnBatteryTimeBase.readSummaryFromParcel(in);
10811        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
10812        mDischargeUnplugLevel = in.readInt();
10813        mDischargePlugLevel = in.readInt();
10814        mDischargeCurrentLevel = in.readInt();
10815        mCurrentBatteryLevel = in.readInt();
10816        mEstimatedBatteryCapacity = in.readInt();
10817        mLowDischargeAmountSinceCharge = in.readInt();
10818        mHighDischargeAmountSinceCharge = in.readInt();
10819        mDischargeAmountScreenOnSinceCharge = in.readInt();
10820        mDischargeAmountScreenOffSinceCharge = in.readInt();
10821        mDischargeStepTracker.readFromParcel(in);
10822        mChargeStepTracker.readFromParcel(in);
10823        mDailyDischargeStepTracker.readFromParcel(in);
10824        mDailyChargeStepTracker.readFromParcel(in);
10825        mDischargeCounter.readSummaryFromParcelLocked(in);
10826        mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
10827        int NPKG = in.readInt();
10828        if (NPKG > 0) {
10829            mDailyPackageChanges = new ArrayList<>(NPKG);
10830            while (NPKG > 0) {
10831                NPKG--;
10832                PackageChange pc = new PackageChange();
10833                pc.mPackageName = in.readString();
10834                pc.mUpdate = in.readInt() != 0;
10835                pc.mVersionCode = in.readInt();
10836                mDailyPackageChanges.add(pc);
10837            }
10838        } else {
10839            mDailyPackageChanges = null;
10840        }
10841        mDailyStartTime = in.readLong();
10842        mNextMinDailyDeadline = in.readLong();
10843        mNextMaxDailyDeadline = in.readLong();
10844
10845        mStartCount++;
10846
10847        mScreenState = Display.STATE_UNKNOWN;
10848        mScreenOnTimer.readSummaryFromParcelLocked(in);
10849        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10850            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
10851        }
10852        mInteractive = false;
10853        mInteractiveTimer.readSummaryFromParcelLocked(in);
10854        mPhoneOn = false;
10855        mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
10856        mLongestLightIdleTime = in.readLong();
10857        mLongestFullIdleTime = in.readLong();
10858        mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
10859        mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
10860        mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
10861        mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
10862        mPhoneOnTimer.readSummaryFromParcelLocked(in);
10863        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10864            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
10865        }
10866        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
10867        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10868            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
10869        }
10870        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10871            mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
10872            mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
10873        }
10874        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10875        mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
10876        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
10877        mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
10878        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
10879        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
10880        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10881        mWifiOn = false;
10882        mWifiOnTimer.readSummaryFromParcelLocked(in);
10883        mGlobalWifiRunning = false;
10884        mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
10885        for (int i=0; i<NUM_WIFI_STATES; i++) {
10886            mWifiStateTimer[i].readSummaryFromParcelLocked(in);
10887        }
10888        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10889            mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
10890        }
10891        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10892            mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
10893        }
10894        mWifiActivity.readSummaryFromParcel(in);
10895        mBluetoothActivity.readSummaryFromParcel(in);
10896        mModemActivity.readSummaryFromParcel(in);
10897        mHasWifiReporting = in.readInt() != 0;
10898        mHasBluetoothReporting = in.readInt() != 0;
10899        mHasModemReporting = in.readInt() != 0;
10900
10901        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
10902        mFlashlightOnNesting = 0;
10903        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
10904        mCameraOnNesting = 0;
10905        mCameraOnTimer.readSummaryFromParcelLocked(in);
10906        mBluetoothScanNesting = 0;
10907        mBluetoothScanTimer.readSummaryFromParcelLocked(in);
10908
10909        int NKW = in.readInt();
10910        if (NKW > 10000) {
10911            throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
10912        }
10913        for (int ikw = 0; ikw < NKW; ikw++) {
10914            if (in.readInt() != 0) {
10915                String kwltName = in.readString();
10916                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
10917            }
10918        }
10919
10920        int NWR = in.readInt();
10921        if (NWR > 10000) {
10922            throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
10923        }
10924        for (int iwr = 0; iwr < NWR; iwr++) {
10925            if (in.readInt() != 0) {
10926                String reasonName = in.readString();
10927                getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
10928            }
10929        }
10930
10931        int NMS = in.readInt();
10932        for (int ims = 0; ims < NMS; ims++) {
10933            if (in.readInt() != 0) {
10934                long kmstName = in.readLong();
10935                getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in);
10936            }
10937        }
10938
10939        final int NU = in.readInt();
10940        if (NU > 10000) {
10941            throw new ParcelFormatException("File corrupt: too many uids " + NU);
10942        }
10943        for (int iu = 0; iu < NU; iu++) {
10944            int uid = in.readInt();
10945            Uid u = new Uid(this, uid);
10946            mUidStats.put(uid, u);
10947
10948            u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
10949
10950            u.mWifiRunning = false;
10951            if (in.readInt() != 0) {
10952                u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
10953            }
10954            u.mFullWifiLockOut = false;
10955            if (in.readInt() != 0) {
10956                u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
10957            }
10958            u.mWifiScanStarted = false;
10959            if (in.readInt() != 0) {
10960                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
10961            }
10962            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
10963            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
10964                if (in.readInt() != 0) {
10965                    u.makeWifiBatchedScanBin(i, null);
10966                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
10967                }
10968            }
10969            u.mWifiMulticastEnabled = false;
10970            if (in.readInt() != 0) {
10971                u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
10972            }
10973            if (in.readInt() != 0) {
10974                u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10975            }
10976            if (in.readInt() != 0) {
10977                u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10978            }
10979            if (in.readInt() != 0) {
10980                u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10981            }
10982            if (in.readInt() != 0) {
10983                u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10984            }
10985            if (in.readInt() != 0) {
10986                u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
10987            }
10988            if (in.readInt() != 0) {
10989                u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
10990            }
10991            u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
10992            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
10993                if (in.readInt() != 0) {
10994                    u.makeProcessState(i, null);
10995                    u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
10996                }
10997            }
10998            if (in.readInt() != 0) {
10999                u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
11000            }
11001
11002            if (in.readInt() != 0) {
11003                if (u.mUserActivityCounters == null) {
11004                    u.initUserActivityLocked();
11005                }
11006                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
11007                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
11008                }
11009            }
11010
11011            if (in.readInt() != 0) {
11012                if (u.mNetworkByteActivityCounters == null) {
11013                    u.initNetworkActivityLocked();
11014                }
11015                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11016                    u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
11017                    u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
11018                }
11019                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
11020                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
11021            }
11022
11023            u.mUserCpuTime.readSummaryFromParcelLocked(in);
11024            u.mSystemCpuTime.readSummaryFromParcelLocked(in);
11025
11026            if (in.readInt() != 0) {
11027                final int numClusters = in.readInt();
11028                if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
11029                    throw new ParcelFormatException("Incompatible cpu cluster arrangement");
11030                }
11031
11032                u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
11033                for (int cluster = 0; cluster < numClusters; cluster++) {
11034                    if (in.readInt() != 0) {
11035                        final int NSB = in.readInt();
11036                        if (mPowerProfile != null &&
11037                                mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
11038                            throw new ParcelFormatException("File corrupt: too many speed bins " +
11039                                    NSB);
11040                        }
11041
11042                        u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB];
11043                        for (int speed = 0; speed < NSB; speed++) {
11044                            if (in.readInt() != 0) {
11045                                u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter(
11046                                        mOnBatteryTimeBase);
11047                                u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in);
11048                            }
11049                        }
11050                    } else {
11051                        u.mCpuClusterSpeed[cluster] = null;
11052                    }
11053                }
11054            } else {
11055                u.mCpuClusterSpeed = null;
11056            }
11057
11058            if (in.readInt() != 0) {
11059                u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
11060                u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
11061            } else {
11062                u.mMobileRadioApWakeupCount = null;
11063            }
11064
11065            if (in.readInt() != 0) {
11066                u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
11067                u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
11068            } else {
11069                u.mWifiRadioApWakeupCount = null;
11070            }
11071
11072            int NW = in.readInt();
11073            if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
11074                throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
11075            }
11076            for (int iw = 0; iw < NW; iw++) {
11077                String wlName = in.readString();
11078                u.readWakeSummaryFromParcelLocked(wlName, in);
11079            }
11080
11081            int NS = in.readInt();
11082            if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
11083                throw new ParcelFormatException("File corrupt: too many syncs " + NS);
11084            }
11085            for (int is = 0; is < NS; is++) {
11086                String name = in.readString();
11087                u.readSyncSummaryFromParcelLocked(name, in);
11088            }
11089
11090            int NJ = in.readInt();
11091            if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
11092                throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
11093            }
11094            for (int ij = 0; ij < NJ; ij++) {
11095                String name = in.readString();
11096                u.readJobSummaryFromParcelLocked(name, in);
11097            }
11098
11099            int NP = in.readInt();
11100            if (NP > 1000) {
11101                throw new ParcelFormatException("File corrupt: too many sensors " + NP);
11102            }
11103            for (int is = 0; is < NP; is++) {
11104                int seNumber = in.readInt();
11105                if (in.readInt() != 0) {
11106                    u.getSensorTimerLocked(seNumber, true).readSummaryFromParcelLocked(in);
11107                }
11108            }
11109
11110            NP = in.readInt();
11111            if (NP > 1000) {
11112                throw new ParcelFormatException("File corrupt: too many processes " + NP);
11113            }
11114            for (int ip = 0; ip < NP; ip++) {
11115                String procName = in.readString();
11116                Uid.Proc p = u.getProcessStatsLocked(procName);
11117                p.mUserTime = p.mLoadedUserTime = in.readLong();
11118                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
11119                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
11120                p.mStarts = p.mLoadedStarts = in.readInt();
11121                p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
11122                p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
11123                p.readExcessivePowerFromParcelLocked(in);
11124            }
11125
11126            NP = in.readInt();
11127            if (NP > 10000) {
11128                throw new ParcelFormatException("File corrupt: too many packages " + NP);
11129            }
11130            for (int ip = 0; ip < NP; ip++) {
11131                String pkgName = in.readString();
11132                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
11133                final int NWA = in.readInt();
11134                if (NWA > 1000) {
11135                    throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
11136                }
11137                p.mWakeupAlarms.clear();
11138                for (int iwa=0; iwa<NWA; iwa++) {
11139                    String tag = in.readString();
11140                    Counter c = new Counter(mOnBatteryTimeBase);
11141                    c.readSummaryFromParcelLocked(in);
11142                    p.mWakeupAlarms.put(tag, c);
11143                }
11144                NS = in.readInt();
11145                if (NS > 1000) {
11146                    throw new ParcelFormatException("File corrupt: too many services " + NS);
11147                }
11148                for (int is = 0; is < NS; is++) {
11149                    String servName = in.readString();
11150                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
11151                    s.mStartTime = s.mLoadedStartTime = in.readLong();
11152                    s.mStarts = s.mLoadedStarts = in.readInt();
11153                    s.mLaunches = s.mLoadedLaunches = in.readInt();
11154                }
11155            }
11156        }
11157    }
11158
11159    /**
11160     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
11161     * disk.  This format does not allow a lossless round-trip.
11162     *
11163     * @param out the Parcel to be written to.
11164     */
11165    public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
11166        pullPendingStateUpdatesLocked();
11167
11168        // Pull the clock time.  This may update the time and make a new history entry
11169        // if we had originally pulled a time before the RTC was set.
11170        long startClockTime = getStartClockTime();
11171
11172        final long NOW_SYS = mClocks.uptimeMillis() * 1000;
11173        final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
11174
11175        out.writeInt(VERSION);
11176
11177        writeHistory(out, inclHistory, true);
11178
11179        out.writeInt(mStartCount);
11180        out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
11181        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
11182        out.writeLong(startClockTime);
11183        out.writeString(mStartPlatformVersion);
11184        out.writeString(mEndPlatformVersion);
11185        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
11186        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
11187        out.writeInt(mDischargeUnplugLevel);
11188        out.writeInt(mDischargePlugLevel);
11189        out.writeInt(mDischargeCurrentLevel);
11190        out.writeInt(mCurrentBatteryLevel);
11191        out.writeInt(mEstimatedBatteryCapacity);
11192        out.writeInt(getLowDischargeAmountSinceCharge());
11193        out.writeInt(getHighDischargeAmountSinceCharge());
11194        out.writeInt(getDischargeAmountScreenOnSinceCharge());
11195        out.writeInt(getDischargeAmountScreenOffSinceCharge());
11196        mDischargeStepTracker.writeToParcel(out);
11197        mChargeStepTracker.writeToParcel(out);
11198        mDailyDischargeStepTracker.writeToParcel(out);
11199        mDailyChargeStepTracker.writeToParcel(out);
11200        mDischargeCounter.writeSummaryFromParcelLocked(out);
11201        mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
11202        if (mDailyPackageChanges != null) {
11203            final int NPKG = mDailyPackageChanges.size();
11204            out.writeInt(NPKG);
11205            for (int i=0; i<NPKG; i++) {
11206                PackageChange pc = mDailyPackageChanges.get(i);
11207                out.writeString(pc.mPackageName);
11208                out.writeInt(pc.mUpdate ? 1 : 0);
11209                out.writeInt(pc.mVersionCode);
11210            }
11211        } else {
11212            out.writeInt(0);
11213        }
11214        out.writeLong(mDailyStartTime);
11215        out.writeLong(mNextMinDailyDeadline);
11216        out.writeLong(mNextMaxDailyDeadline);
11217
11218        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11219        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11220            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11221        }
11222        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11223        mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11224        out.writeLong(mLongestLightIdleTime);
11225        out.writeLong(mLongestFullIdleTime);
11226        mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11227        mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11228        mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11229        mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11230        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11231        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11232            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11233        }
11234        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11235        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11236            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11237        }
11238        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11239            mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
11240            mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
11241        }
11242        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11243        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11244        mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
11245        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
11246        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
11247        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11248        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11249        for (int i=0; i<NUM_WIFI_STATES; i++) {
11250            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11251        }
11252        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11253            mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11254        }
11255        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11256            mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11257        }
11258        mWifiActivity.writeSummaryToParcel(out);
11259        mBluetoothActivity.writeSummaryToParcel(out);
11260        mModemActivity.writeSummaryToParcel(out);
11261        out.writeInt(mHasWifiReporting ? 1 : 0);
11262        out.writeInt(mHasBluetoothReporting ? 1 : 0);
11263        out.writeInt(mHasModemReporting ? 1 : 0);
11264
11265        out.writeInt(mNumConnectivityChange);
11266        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11267        mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11268        mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11269
11270        out.writeInt(mKernelWakelockStats.size());
11271        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11272            Timer kwlt = ent.getValue();
11273            if (kwlt != null) {
11274                out.writeInt(1);
11275                out.writeString(ent.getKey());
11276                kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11277            } else {
11278                out.writeInt(0);
11279            }
11280        }
11281
11282        out.writeInt(mWakeupReasonStats.size());
11283        for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
11284            SamplingTimer timer = ent.getValue();
11285            if (timer != null) {
11286                out.writeInt(1);
11287                out.writeString(ent.getKey());
11288                timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11289            } else {
11290                out.writeInt(0);
11291            }
11292        }
11293
11294        out.writeInt(mKernelMemoryStats.size());
11295        for (int i = 0; i < mKernelMemoryStats.size(); i++) {
11296            Timer kmt = mKernelMemoryStats.valueAt(i);
11297            if (kmt != null) {
11298                out.writeInt(1);
11299                out.writeLong(mKernelMemoryStats.keyAt(i));
11300                kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11301            } else {
11302                out.writeInt(0);
11303            }
11304        }
11305
11306        final int NU = mUidStats.size();
11307        out.writeInt(NU);
11308        for (int iu = 0; iu < NU; iu++) {
11309            out.writeInt(mUidStats.keyAt(iu));
11310            Uid u = mUidStats.valueAt(iu);
11311
11312            u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
11313
11314            if (u.mWifiRunningTimer != null) {
11315                out.writeInt(1);
11316                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11317            } else {
11318                out.writeInt(0);
11319            }
11320            if (u.mFullWifiLockTimer != null) {
11321                out.writeInt(1);
11322                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11323            } else {
11324                out.writeInt(0);
11325            }
11326            if (u.mWifiScanTimer != null) {
11327                out.writeInt(1);
11328                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11329            } else {
11330                out.writeInt(0);
11331            }
11332            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
11333                if (u.mWifiBatchedScanTimer[i] != null) {
11334                    out.writeInt(1);
11335                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11336                } else {
11337                    out.writeInt(0);
11338                }
11339            }
11340            if (u.mWifiMulticastTimer != null) {
11341                out.writeInt(1);
11342                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11343            } else {
11344                out.writeInt(0);
11345            }
11346            if (u.mAudioTurnedOnTimer != null) {
11347                out.writeInt(1);
11348                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11349            } else {
11350                out.writeInt(0);
11351            }
11352            if (u.mVideoTurnedOnTimer != null) {
11353                out.writeInt(1);
11354                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11355            } else {
11356                out.writeInt(0);
11357            }
11358            if (u.mFlashlightTurnedOnTimer != null) {
11359                out.writeInt(1);
11360                u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11361            } else {
11362                out.writeInt(0);
11363            }
11364            if (u.mCameraTurnedOnTimer != null) {
11365                out.writeInt(1);
11366                u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11367            } else {
11368                out.writeInt(0);
11369            }
11370            if (u.mForegroundActivityTimer != null) {
11371                out.writeInt(1);
11372                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11373            } else {
11374                out.writeInt(0);
11375            }
11376            if (u.mBluetoothScanTimer != null) {
11377                out.writeInt(1);
11378                u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11379            } else {
11380                out.writeInt(0);
11381            }
11382            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
11383                if (u.mProcessStateTimer[i] != null) {
11384                    out.writeInt(1);
11385                    u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11386                } else {
11387                    out.writeInt(0);
11388                }
11389            }
11390            if (u.mVibratorOnTimer != null) {
11391                out.writeInt(1);
11392                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11393            } else {
11394                out.writeInt(0);
11395            }
11396
11397            if (u.mUserActivityCounters == null) {
11398                out.writeInt(0);
11399            } else {
11400                out.writeInt(1);
11401                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
11402                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
11403                }
11404            }
11405
11406            if (u.mNetworkByteActivityCounters == null) {
11407                out.writeInt(0);
11408            } else {
11409                out.writeInt(1);
11410                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11411                    u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
11412                    u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
11413                }
11414                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
11415                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
11416            }
11417
11418            u.mUserCpuTime.writeSummaryFromParcelLocked(out);
11419            u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
11420
11421            if (u.mCpuClusterSpeed != null) {
11422                out.writeInt(1);
11423                out.writeInt(u.mCpuClusterSpeed.length);
11424                for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) {
11425                    if (cpuSpeeds != null) {
11426                        out.writeInt(1);
11427                        out.writeInt(cpuSpeeds.length);
11428                        for (LongSamplingCounter c : cpuSpeeds) {
11429                            if (c != null) {
11430                                out.writeInt(1);
11431                                c.writeSummaryFromParcelLocked(out);
11432                            } else {
11433                                out.writeInt(0);
11434                            }
11435                        }
11436                    } else {
11437                        out.writeInt(0);
11438                    }
11439                }
11440            } else {
11441                out.writeInt(0);
11442            }
11443
11444            if (u.mMobileRadioApWakeupCount != null) {
11445                out.writeInt(1);
11446                u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
11447            } else {
11448                out.writeInt(0);
11449            }
11450
11451            if (u.mWifiRadioApWakeupCount != null) {
11452                out.writeInt(1);
11453                u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out);
11454            } else {
11455                out.writeInt(0);
11456            }
11457
11458            final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
11459            int NW = wakeStats.size();
11460            out.writeInt(NW);
11461            for (int iw=0; iw<NW; iw++) {
11462                out.writeString(wakeStats.keyAt(iw));
11463                Uid.Wakelock wl = wakeStats.valueAt(iw);
11464                if (wl.mTimerFull != null) {
11465                    out.writeInt(1);
11466                    wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11467                } else {
11468                    out.writeInt(0);
11469                }
11470                if (wl.mTimerPartial != null) {
11471                    out.writeInt(1);
11472                    wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11473                } else {
11474                    out.writeInt(0);
11475                }
11476                if (wl.mTimerWindow != null) {
11477                    out.writeInt(1);
11478                    wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11479                } else {
11480                    out.writeInt(0);
11481                }
11482                if (wl.mTimerDraw != null) {
11483                    out.writeInt(1);
11484                    wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11485                } else {
11486                    out.writeInt(0);
11487                }
11488            }
11489
11490            final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
11491            int NS = syncStats.size();
11492            out.writeInt(NS);
11493            for (int is=0; is<NS; is++) {
11494                out.writeString(syncStats.keyAt(is));
11495                syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11496            }
11497
11498            final ArrayMap<String, DualTimer> jobStats = u.mJobStats.getMap();
11499            int NJ = jobStats.size();
11500            out.writeInt(NJ);
11501            for (int ij=0; ij<NJ; ij++) {
11502                out.writeString(jobStats.keyAt(ij));
11503                jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11504            }
11505
11506            int NSE = u.mSensorStats.size();
11507            out.writeInt(NSE);
11508            for (int ise=0; ise<NSE; ise++) {
11509                out.writeInt(u.mSensorStats.keyAt(ise));
11510                Uid.Sensor se = u.mSensorStats.valueAt(ise);
11511                if (se.mTimer != null) {
11512                    out.writeInt(1);
11513                    se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
11514                } else {
11515                    out.writeInt(0);
11516                }
11517            }
11518
11519            int NP = u.mProcessStats.size();
11520            out.writeInt(NP);
11521            for (int ip=0; ip<NP; ip++) {
11522                out.writeString(u.mProcessStats.keyAt(ip));
11523                Uid.Proc ps = u.mProcessStats.valueAt(ip);
11524                out.writeLong(ps.mUserTime);
11525                out.writeLong(ps.mSystemTime);
11526                out.writeLong(ps.mForegroundTime);
11527                out.writeInt(ps.mStarts);
11528                out.writeInt(ps.mNumCrashes);
11529                out.writeInt(ps.mNumAnrs);
11530                ps.writeExcessivePowerToParcelLocked(out);
11531            }
11532
11533            NP = u.mPackageStats.size();
11534            out.writeInt(NP);
11535            if (NP > 0) {
11536                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
11537                    : u.mPackageStats.entrySet()) {
11538                    out.writeString(ent.getKey());
11539                    Uid.Pkg ps = ent.getValue();
11540                    final int NWA = ps.mWakeupAlarms.size();
11541                    out.writeInt(NWA);
11542                    for (int iwa=0; iwa<NWA; iwa++) {
11543                        out.writeString(ps.mWakeupAlarms.keyAt(iwa));
11544                        ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
11545                    }
11546                    NS = ps.mServiceStats.size();
11547                    out.writeInt(NS);
11548                    for (int is=0; is<NS; is++) {
11549                        out.writeString(ps.mServiceStats.keyAt(is));
11550                        BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
11551                        long time = ss.getStartTimeToNowLocked(
11552                                mOnBatteryTimeBase.getUptime(NOW_SYS));
11553                        out.writeLong(time);
11554                        out.writeInt(ss.mStarts);
11555                        out.writeInt(ss.mLaunches);
11556                    }
11557                }
11558            }
11559        }
11560    }
11561
11562    public void readFromParcel(Parcel in) {
11563        readFromParcelLocked(in);
11564    }
11565
11566    void readFromParcelLocked(Parcel in) {
11567        int magic = in.readInt();
11568        if (magic != MAGIC) {
11569            throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
11570        }
11571
11572        readHistory(in, false);
11573
11574        mStartCount = in.readInt();
11575        mStartClockTime = in.readLong();
11576        mStartPlatformVersion = in.readString();
11577        mEndPlatformVersion = in.readString();
11578        mUptime = in.readLong();
11579        mUptimeStart = in.readLong();
11580        mRealtime = in.readLong();
11581        mRealtimeStart = in.readLong();
11582        mOnBattery = in.readInt() != 0;
11583        mEstimatedBatteryCapacity = in.readInt();
11584        mOnBatteryInternal = false; // we are no longer really running.
11585        mOnBatteryTimeBase.readFromParcel(in);
11586        mOnBatteryScreenOffTimeBase.readFromParcel(in);
11587
11588        mScreenState = Display.STATE_UNKNOWN;
11589        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
11590        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11591            mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
11592                    mOnBatteryTimeBase, in);
11593        }
11594        mInteractive = false;
11595        mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
11596        mPhoneOn = false;
11597        mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
11598                mOnBatteryTimeBase, in);
11599        mLongestLightIdleTime = in.readLong();
11600        mLongestFullIdleTime = in.readLong();
11601        mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
11602                mOnBatteryTimeBase, in);
11603        mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
11604                mOnBatteryTimeBase, in);
11605        mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
11606                mOnBatteryTimeBase, in);
11607        mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
11608        mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
11609        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11610            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
11611                    null, mOnBatteryTimeBase, in);
11612        }
11613        mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
11614                mOnBatteryTimeBase, in);
11615        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11616            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
11617                    null, mOnBatteryTimeBase, in);
11618        }
11619        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11620            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
11621            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
11622        }
11623        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
11624        mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
11625                mOnBatteryTimeBase, in);
11626        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
11627                mOnBatteryTimeBase, in);
11628        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
11629        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
11630        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
11631        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
11632        mWifiOn = false;
11633        mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
11634        mGlobalWifiRunning = false;
11635        mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
11636                mOnBatteryTimeBase, in);
11637        for (int i=0; i<NUM_WIFI_STATES; i++) {
11638            mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
11639                    null, mOnBatteryTimeBase, in);
11640        }
11641        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11642            mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
11643                    null, mOnBatteryTimeBase, in);
11644        }
11645        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11646            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
11647                    null, mOnBatteryTimeBase, in);
11648        }
11649
11650        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11651                NUM_WIFI_TX_LEVELS, in);
11652        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11653                NUM_BT_TX_LEVELS, in);
11654        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
11655                ModemActivityInfo.TX_POWER_LEVELS, in);
11656        mHasWifiReporting = in.readInt() != 0;
11657        mHasBluetoothReporting = in.readInt() != 0;
11658        mHasModemReporting = in.readInt() != 0;
11659
11660        mNumConnectivityChange = in.readInt();
11661        mLoadedNumConnectivityChange = in.readInt();
11662        mUnpluggedNumConnectivityChange = in.readInt();
11663        mAudioOnNesting = 0;
11664        mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
11665        mVideoOnNesting = 0;
11666        mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
11667        mFlashlightOnNesting = 0;
11668        mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
11669        mCameraOnNesting = 0;
11670        mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
11671        mBluetoothScanNesting = 0;
11672        mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
11673        mDischargeUnplugLevel = in.readInt();
11674        mDischargePlugLevel = in.readInt();
11675        mDischargeCurrentLevel = in.readInt();
11676        mCurrentBatteryLevel = in.readInt();
11677        mLowDischargeAmountSinceCharge = in.readInt();
11678        mHighDischargeAmountSinceCharge = in.readInt();
11679        mDischargeAmountScreenOn = in.readInt();
11680        mDischargeAmountScreenOnSinceCharge = in.readInt();
11681        mDischargeAmountScreenOff = in.readInt();
11682        mDischargeAmountScreenOffSinceCharge = in.readInt();
11683        mDischargeStepTracker.readFromParcel(in);
11684        mChargeStepTracker.readFromParcel(in);
11685        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
11686        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
11687        mLastWriteTime = in.readLong();
11688
11689        mKernelWakelockStats.clear();
11690        int NKW = in.readInt();
11691        for (int ikw = 0; ikw < NKW; ikw++) {
11692            if (in.readInt() != 0) {
11693                String wakelockName = in.readString();
11694                SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
11695                mKernelWakelockStats.put(wakelockName, kwlt);
11696            }
11697        }
11698
11699        mWakeupReasonStats.clear();
11700        int NWR = in.readInt();
11701        for (int iwr = 0; iwr < NWR; iwr++) {
11702            if (in.readInt() != 0) {
11703                String reasonName = in.readString();
11704                SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
11705                mWakeupReasonStats.put(reasonName, timer);
11706            }
11707        }
11708
11709        mKernelMemoryStats.clear();
11710        int nmt = in.readInt();
11711        for (int imt = 0; imt < nmt; imt++) {
11712            if (in.readInt() != 0) {
11713                Long bucket = in.readLong();
11714                SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
11715                mKernelMemoryStats.put(bucket, kmt);
11716            }
11717        }
11718
11719        mPartialTimers.clear();
11720        mFullTimers.clear();
11721        mWindowTimers.clear();
11722        mWifiRunningTimers.clear();
11723        mFullWifiLockTimers.clear();
11724        mWifiScanTimers.clear();
11725        mWifiBatchedScanTimers.clear();
11726        mWifiMulticastTimers.clear();
11727        mAudioTurnedOnTimers.clear();
11728        mVideoTurnedOnTimers.clear();
11729        mFlashlightTurnedOnTimers.clear();
11730        mCameraTurnedOnTimers.clear();
11731
11732        int numUids = in.readInt();
11733        mUidStats.clear();
11734        for (int i = 0; i < numUids; i++) {
11735            int uid = in.readInt();
11736            Uid u = new Uid(this, uid);
11737            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
11738            mUidStats.append(uid, u);
11739        }
11740    }
11741
11742    public void writeToParcel(Parcel out, int flags) {
11743        writeToParcelLocked(out, true, flags);
11744    }
11745
11746    public void writeToParcelWithoutUids(Parcel out, int flags) {
11747        writeToParcelLocked(out, false, flags);
11748    }
11749
11750    @SuppressWarnings("unused")
11751    void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
11752        // Need to update with current kernel wake lock counts.
11753        pullPendingStateUpdatesLocked();
11754
11755        // Pull the clock time.  This may update the time and make a new history entry
11756        // if we had originally pulled a time before the RTC was set.
11757        long startClockTime = getStartClockTime();
11758
11759        final long uSecUptime = mClocks.uptimeMillis() * 1000;
11760        final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
11761        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
11762        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
11763
11764        out.writeInt(MAGIC);
11765
11766        writeHistory(out, true, false);
11767
11768        out.writeInt(mStartCount);
11769        out.writeLong(startClockTime);
11770        out.writeString(mStartPlatformVersion);
11771        out.writeString(mEndPlatformVersion);
11772        out.writeLong(mUptime);
11773        out.writeLong(mUptimeStart);
11774        out.writeLong(mRealtime);
11775        out.writeLong(mRealtimeStart);
11776        out.writeInt(mOnBattery ? 1 : 0);
11777        out.writeInt(mEstimatedBatteryCapacity);
11778        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
11779        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
11780
11781        mScreenOnTimer.writeToParcel(out, uSecRealtime);
11782        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11783            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
11784        }
11785        mInteractiveTimer.writeToParcel(out, uSecRealtime);
11786        mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
11787        out.writeLong(mLongestLightIdleTime);
11788        out.writeLong(mLongestFullIdleTime);
11789        mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
11790        mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
11791        mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
11792        mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
11793        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
11794        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11795            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
11796        }
11797        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
11798        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11799            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
11800        }
11801        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11802            mNetworkByteActivityCounters[i].writeToParcel(out);
11803            mNetworkPacketActivityCounters[i].writeToParcel(out);
11804        }
11805        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
11806        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
11807        mMobileRadioActiveAdjustedTime.writeToParcel(out);
11808        mMobileRadioActiveUnknownTime.writeToParcel(out);
11809        mMobileRadioActiveUnknownCount.writeToParcel(out);
11810        mWifiOnTimer.writeToParcel(out, uSecRealtime);
11811        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
11812        for (int i=0; i<NUM_WIFI_STATES; i++) {
11813            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
11814        }
11815        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11816            mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
11817        }
11818        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11819            mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
11820        }
11821        mWifiActivity.writeToParcel(out, 0);
11822        mBluetoothActivity.writeToParcel(out, 0);
11823        mModemActivity.writeToParcel(out, 0);
11824        out.writeInt(mHasWifiReporting ? 1 : 0);
11825        out.writeInt(mHasBluetoothReporting ? 1 : 0);
11826        out.writeInt(mHasModemReporting ? 1 : 0);
11827
11828        out.writeInt(mNumConnectivityChange);
11829        out.writeInt(mLoadedNumConnectivityChange);
11830        out.writeInt(mUnpluggedNumConnectivityChange);
11831        mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
11832        mCameraOnTimer.writeToParcel(out, uSecRealtime);
11833        mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
11834        out.writeInt(mDischargeUnplugLevel);
11835        out.writeInt(mDischargePlugLevel);
11836        out.writeInt(mDischargeCurrentLevel);
11837        out.writeInt(mCurrentBatteryLevel);
11838        out.writeInt(mLowDischargeAmountSinceCharge);
11839        out.writeInt(mHighDischargeAmountSinceCharge);
11840        out.writeInt(mDischargeAmountScreenOn);
11841        out.writeInt(mDischargeAmountScreenOnSinceCharge);
11842        out.writeInt(mDischargeAmountScreenOff);
11843        out.writeInt(mDischargeAmountScreenOffSinceCharge);
11844        mDischargeStepTracker.writeToParcel(out);
11845        mChargeStepTracker.writeToParcel(out);
11846        mDischargeCounter.writeToParcel(out);
11847        mDischargeScreenOffCounter.writeToParcel(out);
11848        out.writeLong(mLastWriteTime);
11849
11850        if (inclUids) {
11851            out.writeInt(mKernelWakelockStats.size());
11852            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11853                SamplingTimer kwlt = ent.getValue();
11854                if (kwlt != null) {
11855                    out.writeInt(1);
11856                    out.writeString(ent.getKey());
11857                    kwlt.writeToParcel(out, uSecRealtime);
11858                } else {
11859                    out.writeInt(0);
11860                }
11861            }
11862            out.writeInt(mWakeupReasonStats.size());
11863            for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
11864                SamplingTimer timer = ent.getValue();
11865                if (timer != null) {
11866                    out.writeInt(1);
11867                    out.writeString(ent.getKey());
11868                    timer.writeToParcel(out, uSecRealtime);
11869                } else {
11870                    out.writeInt(0);
11871                }
11872            }
11873        } else {
11874            out.writeInt(0);
11875        }
11876
11877        out.writeInt(mKernelMemoryStats.size());
11878        for (int i = 0; i < mKernelMemoryStats.size(); i++) {
11879            SamplingTimer kmt = mKernelMemoryStats.valueAt(i);
11880            if (kmt != null) {
11881                out.writeInt(1);
11882                out.writeLong(mKernelMemoryStats.keyAt(i));
11883                kmt.writeToParcel(out, uSecRealtime);
11884            } else {
11885                out.writeInt(0);
11886            }
11887        }
11888
11889        if (inclUids) {
11890            int size = mUidStats.size();
11891            out.writeInt(size);
11892            for (int i = 0; i < size; i++) {
11893                out.writeInt(mUidStats.keyAt(i));
11894                Uid uid = mUidStats.valueAt(i);
11895
11896                uid.writeToParcelLocked(out, uSecUptime, uSecRealtime);
11897            }
11898        } else {
11899            out.writeInt(0);
11900        }
11901    }
11902
11903    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
11904        new Parcelable.Creator<BatteryStatsImpl>() {
11905        public BatteryStatsImpl createFromParcel(Parcel in) {
11906            return new BatteryStatsImpl(in);
11907        }
11908
11909        public BatteryStatsImpl[] newArray(int size) {
11910            return new BatteryStatsImpl[size];
11911        }
11912    };
11913
11914    public void prepareForDumpLocked() {
11915        // Need to retrieve current kernel wake lock stats before printing.
11916        pullPendingStateUpdatesLocked();
11917
11918        // Pull the clock time.  This may update the time and make a new history entry
11919        // if we had originally pulled a time before the RTC was set.
11920        getStartClockTime();
11921    }
11922
11923    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
11924        if (DEBUG) {
11925            pw.println("mOnBatteryTimeBase:");
11926            mOnBatteryTimeBase.dump(pw, "  ");
11927            pw.println("mOnBatteryScreenOffTimeBase:");
11928            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
11929            Printer pr = new PrintWriterPrinter(pw);
11930            pr.println("*** Screen timer:");
11931            mScreenOnTimer.logState(pr, "  ");
11932            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11933                pr.println("*** Screen brightness #" + i + ":");
11934                mScreenBrightnessTimer[i].logState(pr, "  ");
11935            }
11936            pr.println("*** Interactive timer:");
11937            mInteractiveTimer.logState(pr, "  ");
11938            pr.println("*** Power save mode timer:");
11939            mPowerSaveModeEnabledTimer.logState(pr, "  ");
11940            pr.println("*** Device idle mode light timer:");
11941            mDeviceIdleModeLightTimer.logState(pr, "  ");
11942            pr.println("*** Device idle mode full timer:");
11943            mDeviceIdleModeFullTimer.logState(pr, "  ");
11944            pr.println("*** Device light idling timer:");
11945            mDeviceLightIdlingTimer.logState(pr, "  ");
11946            pr.println("*** Device idling timer:");
11947            mDeviceIdlingTimer.logState(pr, "  ");
11948            pr.println("*** Phone timer:");
11949            mPhoneOnTimer.logState(pr, "  ");
11950            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11951                pr.println("*** Phone signal strength #" + i + ":");
11952                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
11953            }
11954            pr.println("*** Signal scanning :");
11955            mPhoneSignalScanningTimer.logState(pr, "  ");
11956            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11957                pr.println("*** Data connection type #" + i + ":");
11958                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
11959            }
11960            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
11961            pr.println("*** Mobile network active timer:");
11962            mMobileRadioActiveTimer.logState(pr, "  ");
11963            pr.println("*** Mobile network active adjusted timer:");
11964            mMobileRadioActiveAdjustedTime.logState(pr, "  ");
11965            pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
11966            pr.println("*** Wifi timer:");
11967            mWifiOnTimer.logState(pr, "  ");
11968            pr.println("*** WifiRunning timer:");
11969            mGlobalWifiRunningTimer.logState(pr, "  ");
11970            for (int i=0; i<NUM_WIFI_STATES; i++) {
11971                pr.println("*** Wifi state #" + i + ":");
11972                mWifiStateTimer[i].logState(pr, "  ");
11973            }
11974            for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11975                pr.println("*** Wifi suppl state #" + i + ":");
11976                mWifiSupplStateTimer[i].logState(pr, "  ");
11977            }
11978            for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11979                pr.println("*** Wifi signal strength #" + i + ":");
11980                mWifiSignalStrengthsTimer[i].logState(pr, "  ");
11981            }
11982            pr.println("*** Flashlight timer:");
11983            mFlashlightOnTimer.logState(pr, "  ");
11984            pr.println("*** Camera timer:");
11985            mCameraOnTimer.logState(pr, "  ");
11986        }
11987        super.dumpLocked(context, pw, flags, reqUid, histStart);
11988    }
11989}
11990