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