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