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 = 147 + (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    void aggregateLastWakeupUptimeLocked(long uptimeMs) {
3289        if (mLastWakeupReason != null) {
3290            long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
3291            SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
3292            timer.add(deltaUptime * 1000, 1); // time in in microseconds
3293            mLastWakeupReason = null;
3294        }
3295    }
3296
3297    public void noteWakeupReasonLocked(String reason) {
3298        final long elapsedRealtime = mClocks.elapsedRealtime();
3299        final long uptime = mClocks.uptimeMillis();
3300        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
3301                + Integer.toHexString(mHistoryCur.states));
3302        aggregateLastWakeupUptimeLocked(uptime);
3303        mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
3304        mHistoryCur.wakeReasonTag.string = reason;
3305        mHistoryCur.wakeReasonTag.uid = 0;
3306        mLastWakeupReason = reason;
3307        mLastWakeupUptimeMs = uptime;
3308        addHistoryRecordLocked(elapsedRealtime, uptime);
3309    }
3310
3311    public boolean startAddingCpuLocked() {
3312        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
3313        return mOnBatteryInternal;
3314    }
3315
3316    public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
3317                                      int statSystemTime, int statIOWaitTime, int statIrqTime,
3318                                      int statSoftIrqTime, int statIdleTime) {
3319        if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
3320                + " user=" + statUserTime + " sys=" + statSystemTime
3321                + " io=" + statIOWaitTime + " irq=" + statIrqTime
3322                + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
3323        mCurStepCpuUserTime += totalUTime;
3324        mCurStepCpuSystemTime += totalSTime;
3325        mCurStepStatUserTime += statUserTime;
3326        mCurStepStatSystemTime += statSystemTime;
3327        mCurStepStatIOWaitTime += statIOWaitTime;
3328        mCurStepStatIrqTime += statIrqTime;
3329        mCurStepStatSoftIrqTime += statSoftIrqTime;
3330        mCurStepStatIdleTime += statIdleTime;
3331    }
3332
3333    public void noteProcessDiedLocked(int uid, int pid) {
3334        uid = mapUid(uid);
3335        Uid u = mUidStats.get(uid);
3336        if (u != null) {
3337            u.mPids.remove(pid);
3338        }
3339    }
3340
3341    public long getProcessWakeTime(int uid, int pid, long realtime) {
3342        uid = mapUid(uid);
3343        Uid u = mUidStats.get(uid);
3344        if (u != null) {
3345            Uid.Pid p = u.mPids.get(pid);
3346            if (p != null) {
3347                return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
3348            }
3349        }
3350        return 0;
3351    }
3352
3353    public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) {
3354        uid = mapUid(uid);
3355        Uid u = mUidStats.get(uid);
3356        if (u != null) {
3357            u.reportExcessiveWakeLocked(proc, overTime, usedTime);
3358        }
3359    }
3360
3361    public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
3362        uid = mapUid(uid);
3363        Uid u = mUidStats.get(uid);
3364        if (u != null) {
3365            u.reportExcessiveCpuLocked(proc, overTime, usedTime);
3366        }
3367    }
3368
3369    int mSensorNesting;
3370
3371    public void noteStartSensorLocked(int uid, int sensor) {
3372        uid = mapUid(uid);
3373        final long elapsedRealtime = mClocks.elapsedRealtime();
3374        final long uptime = mClocks.uptimeMillis();
3375        if (mSensorNesting == 0) {
3376            mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
3377            if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
3378                    + Integer.toHexString(mHistoryCur.states));
3379            addHistoryRecordLocked(elapsedRealtime, uptime);
3380        }
3381        mSensorNesting++;
3382        getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
3383    }
3384
3385    public void noteStopSensorLocked(int uid, int sensor) {
3386        uid = mapUid(uid);
3387        final long elapsedRealtime = mClocks.elapsedRealtime();
3388        final long uptime = mClocks.uptimeMillis();
3389        mSensorNesting--;
3390        if (mSensorNesting == 0) {
3391            mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
3392            if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
3393                    + Integer.toHexString(mHistoryCur.states));
3394            addHistoryRecordLocked(elapsedRealtime, uptime);
3395        }
3396        getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
3397    }
3398
3399    int mGpsNesting;
3400
3401    public void noteStartGpsLocked(int uid) {
3402        uid = mapUid(uid);
3403        final long elapsedRealtime = mClocks.elapsedRealtime();
3404        final long uptime = mClocks.uptimeMillis();
3405        if (mGpsNesting == 0) {
3406            mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
3407            if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
3408                    + Integer.toHexString(mHistoryCur.states));
3409            addHistoryRecordLocked(elapsedRealtime, uptime);
3410        }
3411        mGpsNesting++;
3412        getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
3413    }
3414
3415    public void noteStopGpsLocked(int uid) {
3416        uid = mapUid(uid);
3417        final long elapsedRealtime = mClocks.elapsedRealtime();
3418        final long uptime = mClocks.uptimeMillis();
3419        mGpsNesting--;
3420        if (mGpsNesting == 0) {
3421            mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
3422            if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
3423                    + Integer.toHexString(mHistoryCur.states));
3424            addHistoryRecordLocked(elapsedRealtime, uptime);
3425        }
3426        getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
3427    }
3428
3429    public void noteScreenStateLocked(int state) {
3430        if (mScreenState != state) {
3431            recordDailyStatsIfNeededLocked(true);
3432            final int oldState = mScreenState;
3433            mScreenState = state;
3434            if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
3435                    + ", newState=" + Display.stateToString(state));
3436
3437            if (state != Display.STATE_UNKNOWN) {
3438                int stepState = state-1;
3439                if (stepState < 4) {
3440                    mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
3441                    mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
3442                } else {
3443                    Slog.wtf(TAG, "Unexpected screen state: " + state);
3444                }
3445            }
3446
3447            if (state == Display.STATE_ON) {
3448                // Screen turning on.
3449                final long elapsedRealtime = mClocks.elapsedRealtime();
3450                final long uptime = mClocks.uptimeMillis();
3451                mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
3452                if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
3453                        + Integer.toHexString(mHistoryCur.states));
3454                addHistoryRecordLocked(elapsedRealtime, uptime);
3455                mScreenOnTimer.startRunningLocked(elapsedRealtime);
3456                if (mScreenBrightnessBin >= 0) {
3457                    mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
3458                }
3459
3460                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
3461                        mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
3462
3463                // Fake a wake lock, so we consider the device waked as long
3464                // as the screen is on.
3465                noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
3466                        elapsedRealtime, uptime);
3467
3468                // Update discharge amounts.
3469                if (mOnBatteryInternal) {
3470                    updateDischargeScreenLevelsLocked(false, true);
3471                }
3472            } else if (oldState == Display.STATE_ON) {
3473                // Screen turning off or dozing.
3474                final long elapsedRealtime = mClocks.elapsedRealtime();
3475                final long uptime = mClocks.uptimeMillis();
3476                mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
3477                if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
3478                        + Integer.toHexString(mHistoryCur.states));
3479                addHistoryRecordLocked(elapsedRealtime, uptime);
3480                mScreenOnTimer.stopRunningLocked(elapsedRealtime);
3481                if (mScreenBrightnessBin >= 0) {
3482                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
3483                }
3484
3485                noteStopWakeLocked(-1, -1, "screen", "screen", WAKE_TYPE_PARTIAL,
3486                        elapsedRealtime, uptime);
3487
3488                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
3489                        mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
3490
3491                // Update discharge amounts.
3492                if (mOnBatteryInternal) {
3493                    updateDischargeScreenLevelsLocked(true, false);
3494                }
3495            }
3496        }
3497    }
3498
3499    public void noteScreenBrightnessLocked(int brightness) {
3500        // Bin the brightness.
3501        int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
3502        if (bin < 0) bin = 0;
3503        else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
3504        if (mScreenBrightnessBin != bin) {
3505            final long elapsedRealtime = mClocks.elapsedRealtime();
3506            final long uptime = mClocks.uptimeMillis();
3507            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
3508                    | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
3509            if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
3510                    + Integer.toHexString(mHistoryCur.states));
3511            addHistoryRecordLocked(elapsedRealtime, uptime);
3512            if (mScreenState == Display.STATE_ON) {
3513                if (mScreenBrightnessBin >= 0) {
3514                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
3515                }
3516                mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
3517            }
3518            mScreenBrightnessBin = bin;
3519        }
3520    }
3521
3522    public void noteUserActivityLocked(int uid, int event) {
3523        if (mOnBatteryInternal) {
3524            uid = mapUid(uid);
3525            getUidStatsLocked(uid).noteUserActivityLocked(event);
3526        }
3527    }
3528
3529    public void noteWakeUpLocked(String reason, int reasonUid) {
3530        final long elapsedRealtime = mClocks.elapsedRealtime();
3531        final long uptime = mClocks.uptimeMillis();
3532        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
3533                reason, reasonUid);
3534    }
3535
3536    public void noteInteractiveLocked(boolean interactive) {
3537        if (mInteractive != interactive) {
3538            final long elapsedRealtime = mClocks.elapsedRealtime();
3539            mInteractive = interactive;
3540            if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
3541            if (interactive) {
3542                mInteractiveTimer.startRunningLocked(elapsedRealtime);
3543            } else {
3544                mInteractiveTimer.stopRunningLocked(elapsedRealtime);
3545            }
3546        }
3547    }
3548
3549    public void noteConnectivityChangedLocked(int type, String extra) {
3550        final long elapsedRealtime = mClocks.elapsedRealtime();
3551        final long uptime = mClocks.uptimeMillis();
3552        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
3553                extra, type);
3554        mNumConnectivityChange++;
3555    }
3556
3557    public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
3558        final long elapsedRealtime = mClocks.elapsedRealtime();
3559        final long uptime = mClocks.uptimeMillis();
3560        if (mMobileRadioPowerState != powerState) {
3561            long realElapsedRealtimeMs;
3562            final boolean active =
3563                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
3564                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
3565            if (active) {
3566                mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
3567                mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
3568            } else {
3569                realElapsedRealtimeMs = timestampNs / (1000*1000);
3570                long lastUpdateTimeMs = mMobileRadioActiveStartTime;
3571                if (realElapsedRealtimeMs < lastUpdateTimeMs) {
3572                    Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
3573                            + " is before start time " + lastUpdateTimeMs);
3574                    realElapsedRealtimeMs = elapsedRealtime;
3575                } else if (realElapsedRealtimeMs < elapsedRealtime) {
3576                    mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
3577                            - realElapsedRealtimeMs);
3578                }
3579                mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
3580            }
3581            if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
3582                    + Integer.toHexString(mHistoryCur.states));
3583            addHistoryRecordLocked(elapsedRealtime, uptime);
3584            mMobileRadioPowerState = powerState;
3585            if (active) {
3586                mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
3587                mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
3588            } else {
3589                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
3590                updateMobileRadioStateLocked(realElapsedRealtimeMs, null);
3591                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
3592            }
3593        }
3594    }
3595
3596    public void notePowerSaveMode(boolean enabled) {
3597        if (mPowerSaveModeEnabled != enabled) {
3598            int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
3599            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
3600            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
3601            final long elapsedRealtime = mClocks.elapsedRealtime();
3602            final long uptime = mClocks.uptimeMillis();
3603            mPowerSaveModeEnabled = enabled;
3604            if (enabled) {
3605                mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
3606                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
3607                        + Integer.toHexString(mHistoryCur.states2));
3608                mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
3609            } else {
3610                mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
3611                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
3612                        + Integer.toHexString(mHistoryCur.states2));
3613                mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
3614            }
3615            addHistoryRecordLocked(elapsedRealtime, uptime);
3616        }
3617    }
3618
3619    public void noteDeviceIdleModeLocked(int mode, String activeReason, int activeUid) {
3620        final long elapsedRealtime = mClocks.elapsedRealtime();
3621        final long uptime = mClocks.uptimeMillis();
3622        boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP;
3623        if (mDeviceIdling && !nowIdling && activeReason == null) {
3624            // We don't go out of general idling mode until explicitly taken out of
3625            // device idle through going active or significant motion.
3626            nowIdling = true;
3627        }
3628        boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
3629        if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
3630            // We don't go out of general light idling mode until explicitly taken out of
3631            // device idle through going active or significant motion.
3632            nowLightIdling = true;
3633        }
3634        if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
3635            addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
3636                    activeReason, activeUid);
3637        }
3638        if (mDeviceIdling != nowIdling) {
3639            mDeviceIdling = nowIdling;
3640            int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
3641            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
3642            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
3643            if (nowIdling) {
3644                mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
3645            } else {
3646                mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
3647            }
3648        }
3649        if (mDeviceLightIdling != nowLightIdling) {
3650            mDeviceLightIdling = nowLightIdling;
3651            if (nowLightIdling) {
3652                mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
3653            } else {
3654                mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
3655            }
3656        }
3657        if (mDeviceIdleMode != mode) {
3658            mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
3659                    | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
3660            if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
3661                    + Integer.toHexString(mHistoryCur.states2));
3662            addHistoryRecordLocked(elapsedRealtime, uptime);
3663            long lastDuration = elapsedRealtime - mLastIdleTimeStart;
3664            mLastIdleTimeStart = elapsedRealtime;
3665            if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
3666                if (lastDuration > mLongestLightIdleTime) {
3667                    mLongestLightIdleTime = lastDuration;
3668                }
3669                mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
3670            } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) {
3671                if (lastDuration > mLongestFullIdleTime) {
3672                    mLongestFullIdleTime = lastDuration;
3673                }
3674                mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
3675            }
3676            if (mode == DEVICE_IDLE_MODE_LIGHT) {
3677                mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
3678            } else if (mode == DEVICE_IDLE_MODE_DEEP) {
3679                mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
3680            }
3681            mDeviceIdleMode = mode;
3682        }
3683    }
3684
3685    public void notePackageInstalledLocked(String pkgName, int versionCode) {
3686        final long elapsedRealtime = mClocks.elapsedRealtime();
3687        final long uptime = mClocks.uptimeMillis();
3688        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
3689                pkgName, versionCode);
3690        PackageChange pc = new PackageChange();
3691        pc.mPackageName = pkgName;
3692        pc.mUpdate = true;
3693        pc.mVersionCode = versionCode;
3694        addPackageChange(pc);
3695    }
3696
3697    public void notePackageUninstalledLocked(String pkgName) {
3698        final long elapsedRealtime = mClocks.elapsedRealtime();
3699        final long uptime = mClocks.uptimeMillis();
3700        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
3701                pkgName, 0);
3702        PackageChange pc = new PackageChange();
3703        pc.mPackageName = pkgName;
3704        pc.mUpdate = true;
3705        addPackageChange(pc);
3706    }
3707
3708    private void addPackageChange(PackageChange pc) {
3709        if (mDailyPackageChanges == null) {
3710            mDailyPackageChanges = new ArrayList<>();
3711        }
3712        mDailyPackageChanges.add(pc);
3713    }
3714
3715    public void notePhoneOnLocked() {
3716        if (!mPhoneOn) {
3717            final long elapsedRealtime = mClocks.elapsedRealtime();
3718            final long uptime = mClocks.uptimeMillis();
3719            mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
3720            if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
3721                    + Integer.toHexString(mHistoryCur.states));
3722            addHistoryRecordLocked(elapsedRealtime, uptime);
3723            mPhoneOn = true;
3724            mPhoneOnTimer.startRunningLocked(elapsedRealtime);
3725        }
3726    }
3727
3728    public void notePhoneOffLocked() {
3729        if (mPhoneOn) {
3730            final long elapsedRealtime = mClocks.elapsedRealtime();
3731            final long uptime = mClocks.uptimeMillis();
3732            mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
3733            if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
3734                    + Integer.toHexString(mHistoryCur.states));
3735            addHistoryRecordLocked(elapsedRealtime, uptime);
3736            mPhoneOn = false;
3737            mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
3738        }
3739    }
3740
3741    void stopAllPhoneSignalStrengthTimersLocked(int except) {
3742        final long elapsedRealtime = mClocks.elapsedRealtime();
3743        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
3744            if (i == except) {
3745                continue;
3746            }
3747            while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
3748                mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
3749            }
3750        }
3751    }
3752
3753    private int fixPhoneServiceState(int state, int signalBin) {
3754        if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
3755            // In this case we will always be STATE_OUT_OF_SERVICE, so need
3756            // to infer that we are scanning from other data.
3757            if (state == ServiceState.STATE_OUT_OF_SERVICE
3758                    && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
3759                state = ServiceState.STATE_IN_SERVICE;
3760            }
3761        }
3762
3763        return state;
3764    }
3765
3766    private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
3767        boolean scanning = false;
3768        boolean newHistory = false;
3769
3770        mPhoneServiceStateRaw = state;
3771        mPhoneSimStateRaw = simState;
3772        mPhoneSignalStrengthBinRaw = strengthBin;
3773
3774        final long elapsedRealtime = mClocks.elapsedRealtime();
3775        final long uptime = mClocks.uptimeMillis();
3776
3777        if (simState == TelephonyManager.SIM_STATE_ABSENT) {
3778            // In this case we will always be STATE_OUT_OF_SERVICE, so need
3779            // to infer that we are scanning from other data.
3780            if (state == ServiceState.STATE_OUT_OF_SERVICE
3781                    && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
3782                state = ServiceState.STATE_IN_SERVICE;
3783            }
3784        }
3785
3786        // If the phone is powered off, stop all timers.
3787        if (state == ServiceState.STATE_POWER_OFF) {
3788            strengthBin = -1;
3789
3790        // If we are in service, make sure the correct signal string timer is running.
3791        } else if (state == ServiceState.STATE_IN_SERVICE) {
3792            // Bin will be changed below.
3793
3794        // If we're out of service, we are in the lowest signal strength
3795        // bin and have the scanning bit set.
3796        } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
3797            scanning = true;
3798            strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
3799            if (!mPhoneSignalScanningTimer.isRunningLocked()) {
3800                mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
3801                newHistory = true;
3802                if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
3803                        + Integer.toHexString(mHistoryCur.states));
3804                mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
3805            }
3806        }
3807
3808        if (!scanning) {
3809            // If we are no longer scanning, then stop the scanning timer.
3810            if (mPhoneSignalScanningTimer.isRunningLocked()) {
3811                mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
3812                if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
3813                        + Integer.toHexString(mHistoryCur.states));
3814                newHistory = true;
3815                mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
3816            }
3817        }
3818
3819        if (mPhoneServiceState != state) {
3820            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
3821                    | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
3822            if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
3823                    + Integer.toHexString(mHistoryCur.states));
3824            newHistory = true;
3825            mPhoneServiceState = state;
3826        }
3827
3828        if (mPhoneSignalStrengthBin != strengthBin) {
3829            if (mPhoneSignalStrengthBin >= 0) {
3830                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
3831                        elapsedRealtime);
3832            }
3833            if (strengthBin >= 0) {
3834                if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
3835                    mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
3836                }
3837                mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
3838                        | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
3839                if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
3840                        + Integer.toHexString(mHistoryCur.states));
3841                newHistory = true;
3842            } else {
3843                stopAllPhoneSignalStrengthTimersLocked(-1);
3844            }
3845            mPhoneSignalStrengthBin = strengthBin;
3846        }
3847
3848        if (newHistory) {
3849            addHistoryRecordLocked(elapsedRealtime, uptime);
3850        }
3851    }
3852
3853    /**
3854     * Telephony stack updates the phone state.
3855     * @param state phone state from ServiceState.getState()
3856     */
3857    public void notePhoneStateLocked(int state, int simState) {
3858        updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
3859    }
3860
3861    public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
3862        // Bin the strength.
3863        int bin = signalStrength.getLevel();
3864        updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
3865    }
3866
3867    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
3868        int bin = DATA_CONNECTION_NONE;
3869        if (hasData) {
3870            switch (dataType) {
3871                case TelephonyManager.NETWORK_TYPE_EDGE:
3872                    bin = DATA_CONNECTION_EDGE;
3873                    break;
3874                case TelephonyManager.NETWORK_TYPE_GPRS:
3875                    bin = DATA_CONNECTION_GPRS;
3876                    break;
3877                case TelephonyManager.NETWORK_TYPE_UMTS:
3878                    bin = DATA_CONNECTION_UMTS;
3879                    break;
3880                case TelephonyManager.NETWORK_TYPE_CDMA:
3881                    bin = DATA_CONNECTION_CDMA;
3882                    break;
3883                case TelephonyManager.NETWORK_TYPE_EVDO_0:
3884                    bin = DATA_CONNECTION_EVDO_0;
3885                    break;
3886                case TelephonyManager.NETWORK_TYPE_EVDO_A:
3887                    bin = DATA_CONNECTION_EVDO_A;
3888                    break;
3889                case TelephonyManager.NETWORK_TYPE_1xRTT:
3890                    bin = DATA_CONNECTION_1xRTT;
3891                    break;
3892                case TelephonyManager.NETWORK_TYPE_HSDPA:
3893                    bin = DATA_CONNECTION_HSDPA;
3894                    break;
3895                case TelephonyManager.NETWORK_TYPE_HSUPA:
3896                    bin = DATA_CONNECTION_HSUPA;
3897                    break;
3898                case TelephonyManager.NETWORK_TYPE_HSPA:
3899                    bin = DATA_CONNECTION_HSPA;
3900                    break;
3901                case TelephonyManager.NETWORK_TYPE_IDEN:
3902                    bin = DATA_CONNECTION_IDEN;
3903                    break;
3904                case TelephonyManager.NETWORK_TYPE_EVDO_B:
3905                    bin = DATA_CONNECTION_EVDO_B;
3906                    break;
3907                case TelephonyManager.NETWORK_TYPE_LTE:
3908                    bin = DATA_CONNECTION_LTE;
3909                    break;
3910                case TelephonyManager.NETWORK_TYPE_EHRPD:
3911                    bin = DATA_CONNECTION_EHRPD;
3912                    break;
3913                case TelephonyManager.NETWORK_TYPE_HSPAP:
3914                    bin = DATA_CONNECTION_HSPAP;
3915                    break;
3916                default:
3917                    bin = DATA_CONNECTION_OTHER;
3918                    break;
3919            }
3920        }
3921        if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
3922        if (mPhoneDataConnectionType != bin) {
3923            final long elapsedRealtime = mClocks.elapsedRealtime();
3924            final long uptime = mClocks.uptimeMillis();
3925            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
3926                    | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
3927            if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
3928                    + Integer.toHexString(mHistoryCur.states));
3929            addHistoryRecordLocked(elapsedRealtime, uptime);
3930            if (mPhoneDataConnectionType >= 0) {
3931                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
3932                        elapsedRealtime);
3933            }
3934            mPhoneDataConnectionType = bin;
3935            mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
3936        }
3937    }
3938
3939    public void noteWifiOnLocked() {
3940        if (!mWifiOn) {
3941            final long elapsedRealtime = mClocks.elapsedRealtime();
3942            final long uptime = mClocks.uptimeMillis();
3943            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
3944            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
3945                    + Integer.toHexString(mHistoryCur.states));
3946            addHistoryRecordLocked(elapsedRealtime, uptime);
3947            mWifiOn = true;
3948            mWifiOnTimer.startRunningLocked(elapsedRealtime);
3949            scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
3950        }
3951    }
3952
3953    public void noteWifiOffLocked() {
3954        final long elapsedRealtime = mClocks.elapsedRealtime();
3955        final long uptime = mClocks.uptimeMillis();
3956        if (mWifiOn) {
3957            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
3958            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
3959                    + Integer.toHexString(mHistoryCur.states));
3960            addHistoryRecordLocked(elapsedRealtime, uptime);
3961            mWifiOn = false;
3962            mWifiOnTimer.stopRunningLocked(elapsedRealtime);
3963            scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
3964        }
3965    }
3966
3967    public void noteAudioOnLocked(int uid) {
3968        uid = mapUid(uid);
3969        final long elapsedRealtime = mClocks.elapsedRealtime();
3970        final long uptime = mClocks.uptimeMillis();
3971        if (mAudioOnNesting == 0) {
3972            mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
3973            if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
3974                    + Integer.toHexString(mHistoryCur.states));
3975            addHistoryRecordLocked(elapsedRealtime, uptime);
3976            mAudioOnTimer.startRunningLocked(elapsedRealtime);
3977        }
3978        mAudioOnNesting++;
3979        getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
3980    }
3981
3982    public void noteAudioOffLocked(int uid) {
3983        if (mAudioOnNesting == 0) {
3984            return;
3985        }
3986        uid = mapUid(uid);
3987        final long elapsedRealtime = mClocks.elapsedRealtime();
3988        final long uptime = mClocks.uptimeMillis();
3989        if (--mAudioOnNesting == 0) {
3990            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
3991            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
3992                    + Integer.toHexString(mHistoryCur.states));
3993            addHistoryRecordLocked(elapsedRealtime, uptime);
3994            mAudioOnTimer.stopRunningLocked(elapsedRealtime);
3995        }
3996        getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
3997    }
3998
3999    public void noteVideoOnLocked(int uid) {
4000        uid = mapUid(uid);
4001        final long elapsedRealtime = mClocks.elapsedRealtime();
4002        final long uptime = mClocks.uptimeMillis();
4003        if (mVideoOnNesting == 0) {
4004            mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
4005            if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
4006                    + Integer.toHexString(mHistoryCur.states));
4007            addHistoryRecordLocked(elapsedRealtime, uptime);
4008            mVideoOnTimer.startRunningLocked(elapsedRealtime);
4009        }
4010        mVideoOnNesting++;
4011        getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
4012    }
4013
4014    public void noteVideoOffLocked(int uid) {
4015        if (mVideoOnNesting == 0) {
4016            return;
4017        }
4018        uid = mapUid(uid);
4019        final long elapsedRealtime = mClocks.elapsedRealtime();
4020        final long uptime = mClocks.uptimeMillis();
4021        if (--mVideoOnNesting == 0) {
4022            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
4023            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
4024                    + Integer.toHexString(mHistoryCur.states));
4025            addHistoryRecordLocked(elapsedRealtime, uptime);
4026            mVideoOnTimer.stopRunningLocked(elapsedRealtime);
4027        }
4028        getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
4029    }
4030
4031    public void noteResetAudioLocked() {
4032        if (mAudioOnNesting > 0) {
4033            final long elapsedRealtime = mClocks.elapsedRealtime();
4034            final long uptime = mClocks.uptimeMillis();
4035            mAudioOnNesting = 0;
4036            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
4037            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
4038                    + Integer.toHexString(mHistoryCur.states));
4039            addHistoryRecordLocked(elapsedRealtime, uptime);
4040            mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
4041            for (int i=0; i<mUidStats.size(); i++) {
4042                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4043                uid.noteResetAudioLocked(elapsedRealtime);
4044            }
4045        }
4046    }
4047
4048    public void noteResetVideoLocked() {
4049        if (mVideoOnNesting > 0) {
4050            final long elapsedRealtime = mClocks.elapsedRealtime();
4051            final long uptime = mClocks.uptimeMillis();
4052            mAudioOnNesting = 0;
4053            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
4054            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
4055                    + Integer.toHexString(mHistoryCur.states));
4056            addHistoryRecordLocked(elapsedRealtime, uptime);
4057            mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
4058            for (int i=0; i<mUidStats.size(); i++) {
4059                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4060                uid.noteResetVideoLocked(elapsedRealtime);
4061            }
4062        }
4063    }
4064
4065    public void noteActivityResumedLocked(int uid) {
4066        uid = mapUid(uid);
4067        getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
4068    }
4069
4070    public void noteActivityPausedLocked(int uid) {
4071        uid = mapUid(uid);
4072        getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
4073    }
4074
4075    public void noteVibratorOnLocked(int uid, long durationMillis) {
4076        uid = mapUid(uid);
4077        getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
4078    }
4079
4080    public void noteVibratorOffLocked(int uid) {
4081        uid = mapUid(uid);
4082        getUidStatsLocked(uid).noteVibratorOffLocked();
4083    }
4084
4085    public void noteFlashlightOnLocked(int uid) {
4086        uid = mapUid(uid);
4087        final long elapsedRealtime = mClocks.elapsedRealtime();
4088        final long uptime = mClocks.uptimeMillis();
4089        if (mFlashlightOnNesting++ == 0) {
4090            mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
4091            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
4092                    + Integer.toHexString(mHistoryCur.states2));
4093            addHistoryRecordLocked(elapsedRealtime, uptime);
4094            mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
4095        }
4096        getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
4097    }
4098
4099    public void noteFlashlightOffLocked(int uid) {
4100        if (mFlashlightOnNesting == 0) {
4101            return;
4102        }
4103        uid = mapUid(uid);
4104        final long elapsedRealtime = mClocks.elapsedRealtime();
4105        final long uptime = mClocks.uptimeMillis();
4106        if (--mFlashlightOnNesting == 0) {
4107            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
4108            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
4109                    + Integer.toHexString(mHistoryCur.states2));
4110            addHistoryRecordLocked(elapsedRealtime, uptime);
4111            mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
4112        }
4113        getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
4114    }
4115
4116    public void noteCameraOnLocked(int uid) {
4117        uid = mapUid(uid);
4118        final long elapsedRealtime = mClocks.elapsedRealtime();
4119        final long uptime = mClocks.uptimeMillis();
4120        if (mCameraOnNesting++ == 0) {
4121            mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
4122            if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
4123                    + Integer.toHexString(mHistoryCur.states2));
4124            addHistoryRecordLocked(elapsedRealtime, uptime);
4125            mCameraOnTimer.startRunningLocked(elapsedRealtime);
4126        }
4127        getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
4128    }
4129
4130    public void noteCameraOffLocked(int uid) {
4131        if (mCameraOnNesting == 0) {
4132            return;
4133        }
4134        uid = mapUid(uid);
4135        final long elapsedRealtime = mClocks.elapsedRealtime();
4136        final long uptime = mClocks.uptimeMillis();
4137        if (--mCameraOnNesting == 0) {
4138            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
4139            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
4140                    + Integer.toHexString(mHistoryCur.states2));
4141            addHistoryRecordLocked(elapsedRealtime, uptime);
4142            mCameraOnTimer.stopRunningLocked(elapsedRealtime);
4143        }
4144        getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
4145    }
4146
4147    public void noteResetCameraLocked() {
4148        if (mCameraOnNesting > 0) {
4149            final long elapsedRealtime = mClocks.elapsedRealtime();
4150            final long uptime = mClocks.uptimeMillis();
4151            mCameraOnNesting = 0;
4152            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
4153            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
4154                    + Integer.toHexString(mHistoryCur.states2));
4155            addHistoryRecordLocked(elapsedRealtime, uptime);
4156            mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
4157            for (int i=0; i<mUidStats.size(); i++) {
4158                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4159                uid.noteResetCameraLocked(elapsedRealtime);
4160            }
4161        }
4162    }
4163
4164    public void noteResetFlashlightLocked() {
4165        if (mFlashlightOnNesting > 0) {
4166            final long elapsedRealtime = mClocks.elapsedRealtime();
4167            final long uptime = mClocks.uptimeMillis();
4168            mFlashlightOnNesting = 0;
4169            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
4170            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
4171                    + Integer.toHexString(mHistoryCur.states2));
4172            addHistoryRecordLocked(elapsedRealtime, uptime);
4173            mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
4174            for (int i=0; i<mUidStats.size(); i++) {
4175                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4176                uid.noteResetFlashlightLocked(elapsedRealtime);
4177            }
4178        }
4179    }
4180
4181    private void noteBluetoothScanStartedLocked(int uid) {
4182        uid = mapUid(uid);
4183        final long elapsedRealtime = SystemClock.elapsedRealtime();
4184        final long uptime = SystemClock.uptimeMillis();
4185        if (mBluetoothScanNesting == 0) {
4186            mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
4187            if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
4188                    + Integer.toHexString(mHistoryCur.states2));
4189            addHistoryRecordLocked(elapsedRealtime, uptime);
4190            mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
4191        }
4192        mBluetoothScanNesting++;
4193        getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime);
4194    }
4195
4196    public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws) {
4197        final int N = ws.size();
4198        for (int i = 0; i < N; i++) {
4199            noteBluetoothScanStartedLocked(ws.get(i));
4200        }
4201    }
4202
4203    private void noteBluetoothScanStoppedLocked(int uid) {
4204        uid = mapUid(uid);
4205        final long elapsedRealtime = SystemClock.elapsedRealtime();
4206        final long uptime = SystemClock.uptimeMillis();
4207        mBluetoothScanNesting--;
4208        if (mBluetoothScanNesting == 0) {
4209            mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
4210            if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
4211                    + Integer.toHexString(mHistoryCur.states2));
4212            addHistoryRecordLocked(elapsedRealtime, uptime);
4213            mBluetoothScanTimer.stopRunningLocked(elapsedRealtime);
4214        }
4215        getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime);
4216    }
4217
4218    public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws) {
4219        final int N = ws.size();
4220        for (int i = 0; i < N; i++) {
4221            noteBluetoothScanStoppedLocked(ws.get(i));
4222        }
4223    }
4224
4225    public void noteResetBluetoothScanLocked() {
4226        if (mBluetoothScanNesting > 0) {
4227            final long elapsedRealtime = SystemClock.elapsedRealtime();
4228            final long uptime = SystemClock.uptimeMillis();
4229            mBluetoothScanNesting = 0;
4230            mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
4231            if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
4232                    + Integer.toHexString(mHistoryCur.states2));
4233            addHistoryRecordLocked(elapsedRealtime, uptime);
4234            mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
4235            for (int i=0; i<mUidStats.size(); i++) {
4236                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
4237                uid.noteResetBluetoothScanLocked(elapsedRealtime);
4238            }
4239        }
4240    }
4241
4242    public void noteWifiRadioPowerState(int powerState, long timestampNs) {
4243        final long elapsedRealtime = mClocks.elapsedRealtime();
4244        final long uptime = mClocks.uptimeMillis();
4245        if (mWifiRadioPowerState != powerState) {
4246            final boolean active =
4247                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
4248                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
4249            if (active) {
4250                mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
4251            } else {
4252                mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
4253            }
4254            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
4255                    + Integer.toHexString(mHistoryCur.states));
4256            addHistoryRecordLocked(elapsedRealtime, uptime);
4257            mWifiRadioPowerState = powerState;
4258        }
4259    }
4260
4261    public void noteWifiRunningLocked(WorkSource ws) {
4262        if (!mGlobalWifiRunning) {
4263            final long elapsedRealtime = mClocks.elapsedRealtime();
4264            final long uptime = mClocks.uptimeMillis();
4265            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
4266            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
4267                    + Integer.toHexString(mHistoryCur.states));
4268            addHistoryRecordLocked(elapsedRealtime, uptime);
4269            mGlobalWifiRunning = true;
4270            mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
4271            int N = ws.size();
4272            for (int i=0; i<N; i++) {
4273                int uid = mapUid(ws.get(i));
4274                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
4275            }
4276            scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
4277        } else {
4278            Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
4279        }
4280    }
4281
4282    public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
4283        if (mGlobalWifiRunning) {
4284            final long elapsedRealtime = mClocks.elapsedRealtime();
4285            int N = oldWs.size();
4286            for (int i=0; i<N; i++) {
4287                int uid = mapUid(oldWs.get(i));
4288                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
4289            }
4290            N = newWs.size();
4291            for (int i=0; i<N; i++) {
4292                int uid = mapUid(newWs.get(i));
4293                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
4294            }
4295        } else {
4296            Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
4297        }
4298    }
4299
4300    public void noteWifiStoppedLocked(WorkSource ws) {
4301        if (mGlobalWifiRunning) {
4302            final long elapsedRealtime = mClocks.elapsedRealtime();
4303            final long uptime = mClocks.uptimeMillis();
4304            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
4305            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
4306                    + Integer.toHexString(mHistoryCur.states));
4307            addHistoryRecordLocked(elapsedRealtime, uptime);
4308            mGlobalWifiRunning = false;
4309            mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
4310            int N = ws.size();
4311            for (int i=0; i<N; i++) {
4312                int uid = mapUid(ws.get(i));
4313                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
4314            }
4315            scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
4316        } else {
4317            Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
4318        }
4319    }
4320
4321    public void noteWifiStateLocked(int wifiState, String accessPoint) {
4322        if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
4323        if (mWifiState != wifiState) {
4324            final long elapsedRealtime = mClocks.elapsedRealtime();
4325            if (mWifiState >= 0) {
4326                mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
4327            }
4328            mWifiState = wifiState;
4329            mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
4330            scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
4331        }
4332    }
4333
4334    public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
4335        if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
4336        if (mWifiSupplState != supplState) {
4337            final long elapsedRealtime = mClocks.elapsedRealtime();
4338            final long uptime = mClocks.uptimeMillis();
4339            if (mWifiSupplState >= 0) {
4340                mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
4341            }
4342            mWifiSupplState = supplState;
4343            mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
4344            mHistoryCur.states2 =
4345                    (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
4346                    | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
4347            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
4348                    + Integer.toHexString(mHistoryCur.states2));
4349            addHistoryRecordLocked(elapsedRealtime, uptime);
4350        }
4351    }
4352
4353    void stopAllWifiSignalStrengthTimersLocked(int except) {
4354        final long elapsedRealtime = mClocks.elapsedRealtime();
4355        for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
4356            if (i == except) {
4357                continue;
4358            }
4359            while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
4360                mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
4361            }
4362        }
4363    }
4364
4365    public void noteWifiRssiChangedLocked(int newRssi) {
4366        int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
4367        if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
4368        if (mWifiSignalStrengthBin != strengthBin) {
4369            final long elapsedRealtime = mClocks.elapsedRealtime();
4370            final long uptime = mClocks.uptimeMillis();
4371            if (mWifiSignalStrengthBin >= 0) {
4372                mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
4373                        elapsedRealtime);
4374            }
4375            if (strengthBin >= 0) {
4376                if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
4377                    mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
4378                }
4379                mHistoryCur.states2 =
4380                        (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
4381                        | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
4382                if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
4383                        + Integer.toHexString(mHistoryCur.states2));
4384                addHistoryRecordLocked(elapsedRealtime, uptime);
4385            } else {
4386                stopAllWifiSignalStrengthTimersLocked(-1);
4387            }
4388            mWifiSignalStrengthBin = strengthBin;
4389        }
4390    }
4391
4392    int mWifiFullLockNesting = 0;
4393
4394    public void noteFullWifiLockAcquiredLocked(int uid) {
4395        uid = mapUid(uid);
4396        final long elapsedRealtime = mClocks.elapsedRealtime();
4397        final long uptime = mClocks.uptimeMillis();
4398        if (mWifiFullLockNesting == 0) {
4399            mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
4400            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
4401                    + Integer.toHexString(mHistoryCur.states));
4402            addHistoryRecordLocked(elapsedRealtime, uptime);
4403        }
4404        mWifiFullLockNesting++;
4405        getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
4406    }
4407
4408    public void noteFullWifiLockReleasedLocked(int uid) {
4409        uid = mapUid(uid);
4410        final long elapsedRealtime = mClocks.elapsedRealtime();
4411        final long uptime = mClocks.uptimeMillis();
4412        mWifiFullLockNesting--;
4413        if (mWifiFullLockNesting == 0) {
4414            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
4415            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
4416                    + Integer.toHexString(mHistoryCur.states));
4417            addHistoryRecordLocked(elapsedRealtime, uptime);
4418        }
4419        getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
4420    }
4421
4422    int mWifiScanNesting = 0;
4423
4424    public void noteWifiScanStartedLocked(int uid) {
4425        uid = mapUid(uid);
4426        final long elapsedRealtime = mClocks.elapsedRealtime();
4427        final long uptime = mClocks.uptimeMillis();
4428        if (mWifiScanNesting == 0) {
4429            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
4430            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
4431                    + Integer.toHexString(mHistoryCur.states));
4432            addHistoryRecordLocked(elapsedRealtime, uptime);
4433        }
4434        mWifiScanNesting++;
4435        getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
4436    }
4437
4438    public void noteWifiScanStoppedLocked(int uid) {
4439        uid = mapUid(uid);
4440        final long elapsedRealtime = mClocks.elapsedRealtime();
4441        final long uptime = mClocks.uptimeMillis();
4442        mWifiScanNesting--;
4443        if (mWifiScanNesting == 0) {
4444            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
4445            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
4446                    + Integer.toHexString(mHistoryCur.states));
4447            addHistoryRecordLocked(elapsedRealtime, uptime);
4448        }
4449        getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
4450    }
4451
4452    public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
4453        uid = mapUid(uid);
4454        final long elapsedRealtime = mClocks.elapsedRealtime();
4455        getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
4456    }
4457
4458    public void noteWifiBatchedScanStoppedLocked(int uid) {
4459        uid = mapUid(uid);
4460        final long elapsedRealtime = mClocks.elapsedRealtime();
4461        getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
4462    }
4463
4464    int mWifiMulticastNesting = 0;
4465
4466    public void noteWifiMulticastEnabledLocked(int uid) {
4467        uid = mapUid(uid);
4468        final long elapsedRealtime = mClocks.elapsedRealtime();
4469        final long uptime = mClocks.uptimeMillis();
4470        if (mWifiMulticastNesting == 0) {
4471            mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
4472            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
4473                    + Integer.toHexString(mHistoryCur.states));
4474            addHistoryRecordLocked(elapsedRealtime, uptime);
4475        }
4476        mWifiMulticastNesting++;
4477        getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
4478    }
4479
4480    public void noteWifiMulticastDisabledLocked(int uid) {
4481        uid = mapUid(uid);
4482        final long elapsedRealtime = mClocks.elapsedRealtime();
4483        final long uptime = mClocks.uptimeMillis();
4484        mWifiMulticastNesting--;
4485        if (mWifiMulticastNesting == 0) {
4486            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
4487            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
4488                    + Integer.toHexString(mHistoryCur.states));
4489            addHistoryRecordLocked(elapsedRealtime, uptime);
4490        }
4491        getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
4492    }
4493
4494    public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
4495        int N = ws.size();
4496        for (int i=0; i<N; i++) {
4497            noteFullWifiLockAcquiredLocked(ws.get(i));
4498        }
4499    }
4500
4501    public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
4502        int N = ws.size();
4503        for (int i=0; i<N; i++) {
4504            noteFullWifiLockReleasedLocked(ws.get(i));
4505        }
4506    }
4507
4508    public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
4509        int N = ws.size();
4510        for (int i=0; i<N; i++) {
4511            noteWifiScanStartedLocked(ws.get(i));
4512        }
4513    }
4514
4515    public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
4516        int N = ws.size();
4517        for (int i=0; i<N; i++) {
4518            noteWifiScanStoppedLocked(ws.get(i));
4519        }
4520    }
4521
4522    public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
4523        int N = ws.size();
4524        for (int i=0; i<N; i++) {
4525            noteWifiBatchedScanStartedLocked(ws.get(i), csph);
4526        }
4527    }
4528
4529    public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
4530        int N = ws.size();
4531        for (int i=0; i<N; i++) {
4532            noteWifiBatchedScanStoppedLocked(ws.get(i));
4533        }
4534    }
4535
4536    public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
4537        int N = ws.size();
4538        for (int i=0; i<N; i++) {
4539            noteWifiMulticastEnabledLocked(ws.get(i));
4540        }
4541    }
4542
4543    public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
4544        int N = ws.size();
4545        for (int i=0; i<N; i++) {
4546            noteWifiMulticastDisabledLocked(ws.get(i));
4547        }
4548    }
4549
4550    private static String[] includeInStringArray(String[] array, String str) {
4551        if (ArrayUtils.indexOf(array, str) >= 0) {
4552            return array;
4553        }
4554        String[] newArray = new String[array.length+1];
4555        System.arraycopy(array, 0, newArray, 0, array.length);
4556        newArray[array.length] = str;
4557        return newArray;
4558    }
4559
4560    private static String[] excludeFromStringArray(String[] array, String str) {
4561        int index = ArrayUtils.indexOf(array, str);
4562        if (index >= 0) {
4563            String[] newArray = new String[array.length-1];
4564            if (index > 0) {
4565                System.arraycopy(array, 0, newArray, 0, index);
4566            }
4567            if (index < array.length-1) {
4568                System.arraycopy(array, index+1, newArray, index, array.length-index-1);
4569            }
4570            return newArray;
4571        }
4572        return array;
4573    }
4574
4575    public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
4576        if (TextUtils.isEmpty(iface)) return;
4577        if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
4578            mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
4579            if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
4580        } else {
4581            mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
4582            if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
4583        }
4584        if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
4585            mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
4586            if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
4587        } else {
4588            mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
4589            if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
4590        }
4591    }
4592
4593    public void noteNetworkStatsEnabledLocked() {
4594        // During device boot, qtaguid isn't enabled until after the inital
4595        // loading of battery stats. Now that they're enabled, take our initial
4596        // snapshot for future delta calculation.
4597        updateMobileRadioStateLocked(mClocks.elapsedRealtime(), null);
4598        updateWifiStateLocked(null);
4599    }
4600
4601    @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
4602        return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4603    }
4604
4605    @Override public int getScreenOnCount(int which) {
4606        return mScreenOnTimer.getCountLocked(which);
4607    }
4608
4609    @Override public long getScreenBrightnessTime(int brightnessBin,
4610            long elapsedRealtimeUs, int which) {
4611        return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
4612                elapsedRealtimeUs, which);
4613    }
4614
4615    @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
4616        return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4617    }
4618
4619    @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
4620        return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4621    }
4622
4623    @Override public int getPowerSaveModeEnabledCount(int which) {
4624        return mPowerSaveModeEnabledTimer.getCountLocked(which);
4625    }
4626
4627    @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
4628            int which) {
4629        switch (mode) {
4630            case DEVICE_IDLE_MODE_LIGHT:
4631                return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4632            case DEVICE_IDLE_MODE_DEEP:
4633                return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4634        }
4635        return 0;
4636    }
4637
4638    @Override public int getDeviceIdleModeCount(int mode, int which) {
4639        switch (mode) {
4640            case DEVICE_IDLE_MODE_LIGHT:
4641                return mDeviceIdleModeLightTimer.getCountLocked(which);
4642            case DEVICE_IDLE_MODE_DEEP:
4643                return mDeviceIdleModeFullTimer.getCountLocked(which);
4644        }
4645        return 0;
4646    }
4647
4648    @Override public long getLongestDeviceIdleModeTime(int mode) {
4649        switch (mode) {
4650            case DEVICE_IDLE_MODE_LIGHT:
4651                return mLongestLightIdleTime;
4652            case DEVICE_IDLE_MODE_DEEP:
4653                return mLongestFullIdleTime;
4654        }
4655        return 0;
4656    }
4657
4658    @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
4659        switch (mode) {
4660            case DEVICE_IDLE_MODE_LIGHT:
4661                return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4662            case DEVICE_IDLE_MODE_DEEP:
4663                return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4664        }
4665        return 0;
4666    }
4667
4668    @Override public int getDeviceIdlingCount(int mode, int which) {
4669        switch (mode) {
4670            case DEVICE_IDLE_MODE_LIGHT:
4671                return mDeviceLightIdlingTimer.getCountLocked(which);
4672            case DEVICE_IDLE_MODE_DEEP:
4673                return mDeviceIdlingTimer.getCountLocked(which);
4674        }
4675        return 0;
4676    }
4677
4678    @Override public int getNumConnectivityChange(int which) {
4679        int val = mNumConnectivityChange;
4680        if (which == STATS_CURRENT) {
4681            val -= mLoadedNumConnectivityChange;
4682        } else if (which == STATS_SINCE_UNPLUGGED) {
4683            val -= mUnpluggedNumConnectivityChange;
4684        }
4685        return val;
4686    }
4687
4688    @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
4689        return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4690    }
4691
4692    @Override public int getPhoneOnCount(int which) {
4693        return mPhoneOnTimer.getCountLocked(which);
4694    }
4695
4696    @Override public long getPhoneSignalStrengthTime(int strengthBin,
4697            long elapsedRealtimeUs, int which) {
4698        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
4699                elapsedRealtimeUs, which);
4700    }
4701
4702    @Override public long getPhoneSignalScanningTime(
4703            long elapsedRealtimeUs, int which) {
4704        return mPhoneSignalScanningTimer.getTotalTimeLocked(
4705                elapsedRealtimeUs, which);
4706    }
4707
4708    @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
4709        return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
4710    }
4711
4712    @Override public long getPhoneDataConnectionTime(int dataType,
4713            long elapsedRealtimeUs, int which) {
4714        return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
4715                elapsedRealtimeUs, which);
4716    }
4717
4718    @Override public int getPhoneDataConnectionCount(int dataType, int which) {
4719        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
4720    }
4721
4722    @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
4723        return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4724    }
4725
4726    @Override public int getMobileRadioActiveCount(int which) {
4727        return mMobileRadioActiveTimer.getCountLocked(which);
4728    }
4729
4730    @Override public long getMobileRadioActiveAdjustedTime(int which) {
4731        return mMobileRadioActiveAdjustedTime.getCountLocked(which);
4732    }
4733
4734    @Override public long getMobileRadioActiveUnknownTime(int which) {
4735        return mMobileRadioActiveUnknownTime.getCountLocked(which);
4736    }
4737
4738    @Override public int getMobileRadioActiveUnknownCount(int which) {
4739        return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
4740    }
4741
4742    @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
4743        return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4744    }
4745
4746    @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
4747        return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4748    }
4749
4750    @Override public long getWifiStateTime(int wifiState,
4751            long elapsedRealtimeUs, int which) {
4752        return mWifiStateTimer[wifiState].getTotalTimeLocked(
4753                elapsedRealtimeUs, which);
4754    }
4755
4756    @Override public int getWifiStateCount(int wifiState, int which) {
4757        return mWifiStateTimer[wifiState].getCountLocked(which);
4758    }
4759
4760    @Override public long getWifiSupplStateTime(int state,
4761            long elapsedRealtimeUs, int which) {
4762        return mWifiSupplStateTimer[state].getTotalTimeLocked(
4763                elapsedRealtimeUs, which);
4764    }
4765
4766    @Override public int getWifiSupplStateCount(int state, int which) {
4767        return mWifiSupplStateTimer[state].getCountLocked(which);
4768    }
4769
4770    @Override public long getWifiSignalStrengthTime(int strengthBin,
4771            long elapsedRealtimeUs, int which) {
4772        return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
4773                elapsedRealtimeUs, which);
4774    }
4775
4776    @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
4777        return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
4778    }
4779
4780    @Override
4781    public ControllerActivityCounter getBluetoothControllerActivity() {
4782        return mBluetoothActivity;
4783    }
4784
4785    @Override
4786    public ControllerActivityCounter getWifiControllerActivity() {
4787        return mWifiActivity;
4788    }
4789
4790    @Override
4791    public ControllerActivityCounter getModemControllerActivity() {
4792        return mModemActivity;
4793    }
4794
4795    @Override
4796    public boolean hasBluetoothActivityReporting() {
4797        return mHasBluetoothReporting;
4798    }
4799
4800    @Override
4801    public boolean hasWifiActivityReporting() {
4802        return mHasWifiReporting;
4803    }
4804
4805    @Override
4806    public boolean hasModemActivityReporting() {
4807        return mHasModemReporting;
4808    }
4809
4810    @Override
4811    public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
4812        return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4813    }
4814
4815    @Override
4816    public long getFlashlightOnCount(int which) {
4817        return mFlashlightOnTimer.getCountLocked(which);
4818    }
4819
4820    @Override
4821    public long getCameraOnTime(long elapsedRealtimeUs, int which) {
4822        return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4823    }
4824
4825    @Override
4826    public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
4827        return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4828    }
4829
4830    @Override
4831    public long getNetworkActivityBytes(int type, int which) {
4832        if (type >= 0 && type < mNetworkByteActivityCounters.length) {
4833            return mNetworkByteActivityCounters[type].getCountLocked(which);
4834        } else {
4835            return 0;
4836        }
4837    }
4838
4839    @Override
4840    public long getNetworkActivityPackets(int type, int which) {
4841        if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
4842            return mNetworkPacketActivityCounters[type].getCountLocked(which);
4843        } else {
4844            return 0;
4845        }
4846    }
4847
4848    @Override public long getStartClockTime() {
4849        final long currentTime = System.currentTimeMillis();
4850        if (ensureStartClockTime(currentTime)) {
4851            recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
4852                    mClocks.uptimeMillis());
4853        }
4854        return mStartClockTime;
4855    }
4856
4857    @Override public String getStartPlatformVersion() {
4858        return mStartPlatformVersion;
4859    }
4860
4861    @Override public String getEndPlatformVersion() {
4862        return mEndPlatformVersion;
4863    }
4864
4865    @Override public int getParcelVersion() {
4866        return VERSION;
4867    }
4868
4869    @Override public boolean getIsOnBattery() {
4870        return mOnBattery;
4871    }
4872
4873    @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
4874        return mUidStats;
4875    }
4876
4877    /**
4878     * The statistics associated with a particular uid.
4879     */
4880    public static class Uid extends BatteryStats.Uid {
4881        /**
4882         * BatteryStatsImpl that we are associated with.
4883         */
4884        protected BatteryStatsImpl mBsi;
4885
4886        final int mUid;
4887
4888        boolean mWifiRunning;
4889        StopwatchTimer mWifiRunningTimer;
4890
4891        boolean mFullWifiLockOut;
4892        StopwatchTimer mFullWifiLockTimer;
4893
4894        boolean mWifiScanStarted;
4895        StopwatchTimer mWifiScanTimer;
4896
4897        static final int NO_BATCHED_SCAN_STARTED = -1;
4898        int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
4899        StopwatchTimer[] mWifiBatchedScanTimer;
4900
4901        boolean mWifiMulticastEnabled;
4902        StopwatchTimer mWifiMulticastTimer;
4903
4904        StopwatchTimer mAudioTurnedOnTimer;
4905        StopwatchTimer mVideoTurnedOnTimer;
4906        StopwatchTimer mFlashlightTurnedOnTimer;
4907        StopwatchTimer mCameraTurnedOnTimer;
4908        StopwatchTimer mForegroundActivityTimer;
4909        StopwatchTimer mBluetoothScanTimer;
4910
4911        int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
4912        StopwatchTimer[] mProcessStateTimer;
4913
4914        BatchTimer mVibratorOnTimer;
4915
4916        Counter[] mUserActivityCounters;
4917
4918        LongSamplingCounter[] mNetworkByteActivityCounters;
4919        LongSamplingCounter[] mNetworkPacketActivityCounters;
4920        LongSamplingCounter mMobileRadioActiveTime;
4921        LongSamplingCounter mMobileRadioActiveCount;
4922
4923        /**
4924         * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
4925         * Can be null if the UID has had no such activity.
4926         */
4927        private ControllerActivityCounterImpl mWifiControllerActivity;
4928
4929        /**
4930         * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
4931         * Can be null if the UID has had no such activity.
4932         */
4933        private ControllerActivityCounterImpl mBluetoothControllerActivity;
4934
4935        /**
4936         * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
4937         * Can be null if the UID has had no such activity.
4938         */
4939        private ControllerActivityCounterImpl mModemControllerActivity;
4940
4941        /**
4942         * The CPU times we had at the last history details update.
4943         */
4944        long mLastStepUserTime;
4945        long mLastStepSystemTime;
4946        long mCurStepUserTime;
4947        long mCurStepSystemTime;
4948
4949        LongSamplingCounter mUserCpuTime;
4950        LongSamplingCounter mSystemCpuTime;
4951        LongSamplingCounter mCpuPower;
4952        LongSamplingCounter[][] mCpuClusterSpeed;
4953
4954        /**
4955         * The statistics we have collected for this uid's wake locks.
4956         */
4957        final OverflowArrayMap<Wakelock> mWakelockStats;
4958
4959        /**
4960         * The statistics we have collected for this uid's syncs.
4961         */
4962        final OverflowArrayMap<StopwatchTimer> mSyncStats;
4963
4964        /**
4965         * The statistics we have collected for this uid's jobs.
4966         */
4967        final OverflowArrayMap<StopwatchTimer> mJobStats;
4968
4969        /**
4970         * The statistics we have collected for this uid's sensor activations.
4971         */
4972        final SparseArray<Sensor> mSensorStats = new SparseArray<>();
4973
4974        /**
4975         * The statistics we have collected for this uid's processes.
4976         */
4977        final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
4978
4979        /**
4980         * The statistics we have collected for this uid's processes.
4981         */
4982        final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
4983
4984        /**
4985         * The transient wake stats we have collected for this uid's pids.
4986         */
4987        final SparseArray<Pid> mPids = new SparseArray<>();
4988
4989        public Uid(BatteryStatsImpl bsi, int uid) {
4990            mBsi = bsi;
4991            mUid = uid;
4992
4993            mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
4994            mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
4995            mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
4996
4997            mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>() {
4998                @Override public Wakelock instantiateObject() {
4999                    return new Wakelock(mBsi, Uid.this);
5000                }
5001            };
5002            mSyncStats = mBsi.new OverflowArrayMap<StopwatchTimer>() {
5003                @Override public StopwatchTimer instantiateObject() {
5004                    return new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null,
5005                            mBsi.mOnBatteryTimeBase);
5006                }
5007            };
5008            mJobStats = mBsi.new OverflowArrayMap<StopwatchTimer>() {
5009                @Override public StopwatchTimer instantiateObject() {
5010                    return new StopwatchTimer(mBsi.mClocks, Uid.this, JOB, null,
5011                            mBsi.mOnBatteryTimeBase);
5012                }
5013            };
5014
5015            mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
5016                    mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
5017            mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
5018                    mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
5019            mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_SCAN,
5020                    mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase);
5021            mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
5022            mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
5023                    mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
5024            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
5025        }
5026
5027        @Override
5028        public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
5029            return mWakelockStats.getMap();
5030        }
5031
5032        @Override
5033        public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
5034            return mSyncStats.getMap();
5035        }
5036
5037        @Override
5038        public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
5039            return mJobStats.getMap();
5040        }
5041
5042        @Override
5043        public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
5044            return mSensorStats;
5045        }
5046
5047        @Override
5048        public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
5049            return mProcessStats;
5050        }
5051
5052        @Override
5053        public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
5054            return mPackageStats;
5055        }
5056
5057        @Override
5058        public int getUid() {
5059            return mUid;
5060        }
5061
5062        @Override
5063        public void noteWifiRunningLocked(long elapsedRealtimeMs) {
5064            if (!mWifiRunning) {
5065                mWifiRunning = true;
5066                if (mWifiRunningTimer == null) {
5067                    mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
5068                            mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
5069                }
5070                mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
5071            }
5072        }
5073
5074        @Override
5075        public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
5076            if (mWifiRunning) {
5077                mWifiRunning = false;
5078                mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
5079            }
5080        }
5081
5082        @Override
5083        public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
5084            if (!mFullWifiLockOut) {
5085                mFullWifiLockOut = true;
5086                if (mFullWifiLockTimer == null) {
5087                    mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
5088                            mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
5089                }
5090                mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
5091            }
5092        }
5093
5094        @Override
5095        public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
5096            if (mFullWifiLockOut) {
5097                mFullWifiLockOut = false;
5098                mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
5099            }
5100        }
5101
5102        @Override
5103        public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
5104            if (!mWifiScanStarted) {
5105                mWifiScanStarted = true;
5106                if (mWifiScanTimer == null) {
5107                    mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
5108                            mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase);
5109                }
5110                mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
5111            }
5112        }
5113
5114        @Override
5115        public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
5116            if (mWifiScanStarted) {
5117                mWifiScanStarted = false;
5118                mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
5119            }
5120        }
5121
5122        @Override
5123        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
5124            int bin = 0;
5125            while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
5126                csph = csph >> 3;
5127                bin++;
5128            }
5129
5130            if (mWifiBatchedScanBinStarted == bin) return;
5131
5132            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
5133                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
5134                        stopRunningLocked(elapsedRealtimeMs);
5135            }
5136            mWifiBatchedScanBinStarted = bin;
5137            if (mWifiBatchedScanTimer[bin] == null) {
5138                makeWifiBatchedScanBin(bin, null);
5139            }
5140            mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
5141        }
5142
5143        @Override
5144        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
5145            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
5146                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
5147                        stopRunningLocked(elapsedRealtimeMs);
5148                mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
5149            }
5150        }
5151
5152        @Override
5153        public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
5154            if (!mWifiMulticastEnabled) {
5155                mWifiMulticastEnabled = true;
5156                if (mWifiMulticastTimer == null) {
5157                    mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
5158                            WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
5159                }
5160                mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
5161            }
5162        }
5163
5164        @Override
5165        public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
5166            if (mWifiMulticastEnabled) {
5167                mWifiMulticastEnabled = false;
5168                mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
5169            }
5170        }
5171
5172        @Override
5173        public ControllerActivityCounter getWifiControllerActivity() {
5174            return mWifiControllerActivity;
5175        }
5176
5177        @Override
5178        public ControllerActivityCounter getBluetoothControllerActivity() {
5179            return mBluetoothControllerActivity;
5180        }
5181
5182        @Override
5183        public ControllerActivityCounter getModemControllerActivity() {
5184            return mModemControllerActivity;
5185        }
5186
5187        public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
5188            if (mWifiControllerActivity == null) {
5189                mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
5190                        NUM_BT_TX_LEVELS);
5191            }
5192            return mWifiControllerActivity;
5193        }
5194
5195        public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
5196            if (mBluetoothControllerActivity == null) {
5197                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
5198                        NUM_BT_TX_LEVELS);
5199            }
5200            return mBluetoothControllerActivity;
5201        }
5202
5203        public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
5204            if (mModemControllerActivity == null) {
5205                mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
5206                        ModemActivityInfo.TX_POWER_LEVELS);
5207            }
5208            return mModemControllerActivity;
5209        }
5210
5211        public StopwatchTimer createAudioTurnedOnTimerLocked() {
5212            if (mAudioTurnedOnTimer == null) {
5213                mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
5214                        mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5215            }
5216            return mAudioTurnedOnTimer;
5217        }
5218
5219        public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
5220            createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5221        }
5222
5223        public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
5224            if (mAudioTurnedOnTimer != null) {
5225                mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5226            }
5227        }
5228
5229        public void noteResetAudioLocked(long elapsedRealtimeMs) {
5230            if (mAudioTurnedOnTimer != null) {
5231                mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5232            }
5233        }
5234
5235        public StopwatchTimer createVideoTurnedOnTimerLocked() {
5236            if (mVideoTurnedOnTimer == null) {
5237                mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
5238                        mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5239            }
5240            return mVideoTurnedOnTimer;
5241        }
5242
5243        public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
5244            createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5245        }
5246
5247        public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
5248            if (mVideoTurnedOnTimer != null) {
5249                mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5250            }
5251        }
5252
5253        public void noteResetVideoLocked(long elapsedRealtimeMs) {
5254            if (mVideoTurnedOnTimer != null) {
5255                mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5256            }
5257        }
5258
5259        public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
5260            if (mFlashlightTurnedOnTimer == null) {
5261                mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
5262                        FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5263            }
5264            return mFlashlightTurnedOnTimer;
5265        }
5266
5267        public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
5268            createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5269        }
5270
5271        public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
5272            if (mFlashlightTurnedOnTimer != null) {
5273                mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5274            }
5275        }
5276
5277        public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
5278            if (mFlashlightTurnedOnTimer != null) {
5279                mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5280            }
5281        }
5282
5283        public StopwatchTimer createCameraTurnedOnTimerLocked() {
5284            if (mCameraTurnedOnTimer == null) {
5285                mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
5286                        mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
5287            }
5288            return mCameraTurnedOnTimer;
5289        }
5290
5291        public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
5292            createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
5293        }
5294
5295        public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
5296            if (mCameraTurnedOnTimer != null) {
5297                mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
5298            }
5299        }
5300
5301        public void noteResetCameraLocked(long elapsedRealtimeMs) {
5302            if (mCameraTurnedOnTimer != null) {
5303                mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
5304            }
5305        }
5306
5307        public StopwatchTimer createForegroundActivityTimerLocked() {
5308            if (mForegroundActivityTimer == null) {
5309                mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
5310                        FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
5311            }
5312            return mForegroundActivityTimer;
5313        }
5314
5315        public StopwatchTimer createBluetoothScanTimerLocked() {
5316            if (mBluetoothScanTimer == null) {
5317                mBluetoothScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
5318                        mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase);
5319            }
5320            return mBluetoothScanTimer;
5321        }
5322
5323        public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs) {
5324            createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
5325        }
5326
5327        public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs) {
5328            if (mBluetoothScanTimer != null) {
5329                mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
5330            }
5331        }
5332
5333        public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
5334            if (mBluetoothScanTimer != null) {
5335                mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
5336            }
5337        }
5338
5339        @Override
5340        public void noteActivityResumedLocked(long elapsedRealtimeMs) {
5341            // We always start, since we want multiple foreground PIDs to nest
5342            createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
5343        }
5344
5345        @Override
5346        public void noteActivityPausedLocked(long elapsedRealtimeMs) {
5347            if (mForegroundActivityTimer != null) {
5348                mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
5349            }
5350        }
5351
5352        public BatchTimer createVibratorOnTimerLocked() {
5353            if (mVibratorOnTimer == null) {
5354                mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
5355                        mBsi.mOnBatteryTimeBase);
5356            }
5357            return mVibratorOnTimer;
5358        }
5359
5360        public void noteVibratorOnLocked(long durationMillis) {
5361            createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
5362        }
5363
5364        public void noteVibratorOffLocked() {
5365            if (mVibratorOnTimer != null) {
5366                mVibratorOnTimer.abortLastDuration(mBsi);
5367            }
5368        }
5369
5370        @Override
5371        public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
5372            if (mWifiRunningTimer == null) {
5373                return 0;
5374            }
5375            return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5376        }
5377
5378        @Override
5379        public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
5380            if (mFullWifiLockTimer == null) {
5381                return 0;
5382            }
5383            return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5384        }
5385
5386        @Override
5387        public long getWifiScanTime(long elapsedRealtimeUs, int which) {
5388            if (mWifiScanTimer == null) {
5389                return 0;
5390            }
5391            return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5392        }
5393
5394        @Override
5395        public int getWifiScanCount(int which) {
5396            if (mWifiScanTimer == null) {
5397                return 0;
5398            }
5399            return mWifiScanTimer.getCountLocked(which);
5400        }
5401
5402        @Override
5403        public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
5404            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
5405            if (mWifiBatchedScanTimer[csphBin] == null) {
5406                return 0;
5407            }
5408            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
5409        }
5410
5411        @Override
5412        public int getWifiBatchedScanCount(int csphBin, int which) {
5413            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
5414            if (mWifiBatchedScanTimer[csphBin] == null) {
5415                return 0;
5416            }
5417            return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
5418        }
5419
5420        @Override
5421        public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
5422            if (mWifiMulticastTimer == null) {
5423                return 0;
5424            }
5425            return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
5426        }
5427
5428        @Override
5429        public Timer getAudioTurnedOnTimer() {
5430            return mAudioTurnedOnTimer;
5431        }
5432
5433        @Override
5434        public Timer getVideoTurnedOnTimer() {
5435            return mVideoTurnedOnTimer;
5436        }
5437
5438        @Override
5439        public Timer getFlashlightTurnedOnTimer() {
5440            return mFlashlightTurnedOnTimer;
5441        }
5442
5443        @Override
5444        public Timer getCameraTurnedOnTimer() {
5445            return mCameraTurnedOnTimer;
5446        }
5447
5448        @Override
5449        public Timer getForegroundActivityTimer() {
5450            return mForegroundActivityTimer;
5451        }
5452
5453        @Override
5454        public Timer getBluetoothScanTimer() {
5455            return mBluetoothScanTimer;
5456        }
5457
5458        void makeProcessState(int i, Parcel in) {
5459            if (i < 0 || i >= NUM_PROCESS_STATE) return;
5460
5461            if (in == null) {
5462                mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
5463                        mBsi.mOnBatteryTimeBase);
5464            } else {
5465                mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
5466                        mBsi.mOnBatteryTimeBase, in);
5467            }
5468        }
5469
5470        @Override
5471        public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
5472            if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
5473            if (mProcessStateTimer[state] == null) {
5474                return 0;
5475            }
5476            return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
5477        }
5478
5479        @Override
5480        public Timer getProcessStateTimer(int state) {
5481            if (state < 0 || state >= NUM_PROCESS_STATE) return null;
5482            return mProcessStateTimer[state];
5483        }
5484
5485        @Override
5486        public Timer getVibratorOnTimer() {
5487            return mVibratorOnTimer;
5488        }
5489
5490        @Override
5491        public void noteUserActivityLocked(int type) {
5492            if (mUserActivityCounters == null) {
5493                initUserActivityLocked();
5494            }
5495            if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
5496                mUserActivityCounters[type].stepAtomic();
5497            } else {
5498                Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
5499                        new Throwable());
5500            }
5501        }
5502
5503        @Override
5504        public boolean hasUserActivity() {
5505            return mUserActivityCounters != null;
5506        }
5507
5508        @Override
5509        public int getUserActivityCount(int type, int which) {
5510            if (mUserActivityCounters == null) {
5511                return 0;
5512            }
5513            return mUserActivityCounters[type].getCountLocked(which);
5514        }
5515
5516        void makeWifiBatchedScanBin(int i, Parcel in) {
5517            if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
5518
5519            ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
5520            if (collected == null) {
5521                collected = new ArrayList<StopwatchTimer>();
5522                mBsi.mWifiBatchedScanTimers.put(i, collected);
5523            }
5524            if (in == null) {
5525                mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
5526                        collected, mBsi.mOnBatteryTimeBase);
5527            } else {
5528                mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
5529                        collected, mBsi.mOnBatteryTimeBase, in);
5530            }
5531        }
5532
5533
5534        void initUserActivityLocked() {
5535            mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
5536            for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5537                mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
5538            }
5539        }
5540
5541        void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
5542            if (mNetworkByteActivityCounters == null) {
5543                initNetworkActivityLocked();
5544            }
5545            if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
5546                mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
5547                mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
5548            } else {
5549                Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
5550                        new Throwable());
5551            }
5552        }
5553
5554        void noteMobileRadioActiveTimeLocked(long batteryUptime) {
5555            if (mNetworkByteActivityCounters == null) {
5556                initNetworkActivityLocked();
5557            }
5558            mMobileRadioActiveTime.addCountLocked(batteryUptime);
5559            mMobileRadioActiveCount.addCountLocked(1);
5560        }
5561
5562        @Override
5563        public boolean hasNetworkActivity() {
5564            return mNetworkByteActivityCounters != null;
5565        }
5566
5567        @Override
5568        public long getNetworkActivityBytes(int type, int which) {
5569            if (mNetworkByteActivityCounters != null && type >= 0
5570                    && type < mNetworkByteActivityCounters.length) {
5571                return mNetworkByteActivityCounters[type].getCountLocked(which);
5572            } else {
5573                return 0;
5574            }
5575        }
5576
5577        @Override
5578        public long getNetworkActivityPackets(int type, int which) {
5579            if (mNetworkPacketActivityCounters != null && type >= 0
5580                    && type < mNetworkPacketActivityCounters.length) {
5581                return mNetworkPacketActivityCounters[type].getCountLocked(which);
5582            } else {
5583                return 0;
5584            }
5585        }
5586
5587        @Override
5588        public long getMobileRadioActiveTime(int which) {
5589            return mMobileRadioActiveTime != null
5590                    ? mMobileRadioActiveTime.getCountLocked(which) : 0;
5591        }
5592
5593        @Override
5594        public int getMobileRadioActiveCount(int which) {
5595            return mMobileRadioActiveCount != null
5596                    ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
5597        }
5598
5599        @Override
5600        public long getUserCpuTimeUs(int which) {
5601            return mUserCpuTime.getCountLocked(which);
5602        }
5603
5604        @Override
5605        public long getSystemCpuTimeUs(int which) {
5606            return mSystemCpuTime.getCountLocked(which);
5607        }
5608
5609        @Override
5610        public long getCpuPowerMaUs(int which) {
5611            return mCpuPower.getCountLocked(which);
5612        }
5613
5614        @Override
5615        public long getTimeAtCpuSpeed(int cluster, int step, int which) {
5616            if (mCpuClusterSpeed != null) {
5617                if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
5618                    final LongSamplingCounter[] cpuSpeeds = mCpuClusterSpeed[cluster];
5619                    if (cpuSpeeds != null) {
5620                        if (step >= 0 && step < cpuSpeeds.length) {
5621                            final LongSamplingCounter c = cpuSpeeds[step];
5622                            if (c != null) {
5623                                return c.getCountLocked(which);
5624                            }
5625                        }
5626                    }
5627                }
5628            }
5629            return 0;
5630        }
5631
5632        void initNetworkActivityLocked() {
5633            mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5634            mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5635            for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5636                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5637                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5638            }
5639            mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5640            mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
5641        }
5642
5643        /**
5644         * Clear all stats for this uid.  Returns true if the uid is completely
5645         * inactive so can be dropped.
5646         */
5647        boolean reset() {
5648            boolean active = false;
5649
5650            if (mWifiRunningTimer != null) {
5651                active |= !mWifiRunningTimer.reset(false);
5652                active |= mWifiRunning;
5653            }
5654            if (mFullWifiLockTimer != null) {
5655                active |= !mFullWifiLockTimer.reset(false);
5656                active |= mFullWifiLockOut;
5657            }
5658            if (mWifiScanTimer != null) {
5659                active |= !mWifiScanTimer.reset(false);
5660                active |= mWifiScanStarted;
5661            }
5662            if (mWifiBatchedScanTimer != null) {
5663                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5664                    if (mWifiBatchedScanTimer[i] != null) {
5665                        active |= !mWifiBatchedScanTimer[i].reset(false);
5666                    }
5667                }
5668                active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
5669            }
5670            if (mWifiMulticastTimer != null) {
5671                active |= !mWifiMulticastTimer.reset(false);
5672                active |= mWifiMulticastEnabled;
5673            }
5674            if (mAudioTurnedOnTimer != null) {
5675                active |= !mAudioTurnedOnTimer.reset(false);
5676            }
5677            if (mVideoTurnedOnTimer != null) {
5678                active |= !mVideoTurnedOnTimer.reset(false);
5679            }
5680            if (mFlashlightTurnedOnTimer != null) {
5681                active |= !mFlashlightTurnedOnTimer.reset(false);
5682            }
5683            if (mCameraTurnedOnTimer != null) {
5684                active |= !mCameraTurnedOnTimer.reset(false);
5685            }
5686            if (mForegroundActivityTimer != null) {
5687                active |= !mForegroundActivityTimer.reset(false);
5688            }
5689            if (mBluetoothScanTimer != null) {
5690                active |= !mBluetoothScanTimer.reset(false);
5691            }
5692            if (mProcessStateTimer != null) {
5693                for (int i = 0; i < NUM_PROCESS_STATE; i++) {
5694                    if (mProcessStateTimer[i] != null) {
5695                        active |= !mProcessStateTimer[i].reset(false);
5696                    }
5697                }
5698                active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
5699            }
5700            if (mVibratorOnTimer != null) {
5701                if (mVibratorOnTimer.reset(false)) {
5702                    mVibratorOnTimer.detach();
5703                    mVibratorOnTimer = null;
5704                } else {
5705                    active = true;
5706                }
5707            }
5708
5709            if (mUserActivityCounters != null) {
5710                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5711                    mUserActivityCounters[i].reset(false);
5712                }
5713            }
5714
5715            if (mNetworkByteActivityCounters != null) {
5716                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5717                    mNetworkByteActivityCounters[i].reset(false);
5718                    mNetworkPacketActivityCounters[i].reset(false);
5719                }
5720                mMobileRadioActiveTime.reset(false);
5721                mMobileRadioActiveCount.reset(false);
5722            }
5723
5724            if (mWifiControllerActivity != null) {
5725                mWifiControllerActivity.reset(false);
5726            }
5727
5728            if (mBluetoothControllerActivity != null) {
5729                mBluetoothControllerActivity.reset(false);
5730            }
5731
5732            if (mModemControllerActivity != null) {
5733                mModemControllerActivity.reset(false);
5734            }
5735
5736            mUserCpuTime.reset(false);
5737            mSystemCpuTime.reset(false);
5738            mCpuPower.reset(false);
5739
5740            if (mCpuClusterSpeed != null) {
5741                for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
5742                    if (speeds != null) {
5743                        for (LongSamplingCounter speed : speeds) {
5744                            if (speed != null) {
5745                                speed.reset(false);
5746                            }
5747                        }
5748                    }
5749                }
5750            }
5751
5752            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
5753            for (int iw=wakeStats.size()-1; iw>=0; iw--) {
5754                Wakelock wl = wakeStats.valueAt(iw);
5755                if (wl.reset()) {
5756                    wakeStats.removeAt(iw);
5757                } else {
5758                    active = true;
5759                }
5760            }
5761            mWakelockStats.cleanup();
5762            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
5763            for (int is=syncStats.size()-1; is>=0; is--) {
5764                StopwatchTimer timer = syncStats.valueAt(is);
5765                if (timer.reset(false)) {
5766                    syncStats.removeAt(is);
5767                    timer.detach();
5768                } else {
5769                    active = true;
5770                }
5771            }
5772            mSyncStats.cleanup();
5773            final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
5774            for (int ij=jobStats.size()-1; ij>=0; ij--) {
5775                StopwatchTimer timer = jobStats.valueAt(ij);
5776                if (timer.reset(false)) {
5777                    jobStats.removeAt(ij);
5778                    timer.detach();
5779                } else {
5780                    active = true;
5781                }
5782            }
5783            mJobStats.cleanup();
5784            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
5785                Sensor s = mSensorStats.valueAt(ise);
5786                if (s.reset()) {
5787                    mSensorStats.removeAt(ise);
5788                } else {
5789                    active = true;
5790                }
5791            }
5792            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
5793                Proc proc = mProcessStats.valueAt(ip);
5794                proc.detach();
5795            }
5796            mProcessStats.clear();
5797            if (mPids.size() > 0) {
5798                for (int i=mPids.size()-1; i>=0; i--) {
5799                    Pid pid = mPids.valueAt(i);
5800                    if (pid.mWakeNesting > 0) {
5801                        active = true;
5802                    } else {
5803                        mPids.removeAt(i);
5804                    }
5805                }
5806            }
5807            if (mPackageStats.size() > 0) {
5808                Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
5809                while (it.hasNext()) {
5810                    Map.Entry<String, Pkg> pkgEntry = it.next();
5811                    Pkg p = pkgEntry.getValue();
5812                    p.detach();
5813                    if (p.mServiceStats.size() > 0) {
5814                        Iterator<Map.Entry<String, Pkg.Serv>> it2
5815                                = p.mServiceStats.entrySet().iterator();
5816                        while (it2.hasNext()) {
5817                            Map.Entry<String, Pkg.Serv> servEntry = it2.next();
5818                            servEntry.getValue().detach();
5819                        }
5820                    }
5821                }
5822                mPackageStats.clear();
5823            }
5824
5825            mLastStepUserTime = mLastStepSystemTime = 0;
5826            mCurStepUserTime = mCurStepSystemTime = 0;
5827
5828            if (!active) {
5829                if (mWifiRunningTimer != null) {
5830                    mWifiRunningTimer.detach();
5831                }
5832                if (mFullWifiLockTimer != null) {
5833                    mFullWifiLockTimer.detach();
5834                }
5835                if (mWifiScanTimer != null) {
5836                    mWifiScanTimer.detach();
5837                }
5838                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5839                    if (mWifiBatchedScanTimer[i] != null) {
5840                        mWifiBatchedScanTimer[i].detach();
5841                    }
5842                }
5843                if (mWifiMulticastTimer != null) {
5844                    mWifiMulticastTimer.detach();
5845                }
5846                if (mAudioTurnedOnTimer != null) {
5847                    mAudioTurnedOnTimer.detach();
5848                    mAudioTurnedOnTimer = null;
5849                }
5850                if (mVideoTurnedOnTimer != null) {
5851                    mVideoTurnedOnTimer.detach();
5852                    mVideoTurnedOnTimer = null;
5853                }
5854                if (mFlashlightTurnedOnTimer != null) {
5855                    mFlashlightTurnedOnTimer.detach();
5856                    mFlashlightTurnedOnTimer = null;
5857                }
5858                if (mCameraTurnedOnTimer != null) {
5859                    mCameraTurnedOnTimer.detach();
5860                    mCameraTurnedOnTimer = null;
5861                }
5862                if (mForegroundActivityTimer != null) {
5863                    mForegroundActivityTimer.detach();
5864                    mForegroundActivityTimer = null;
5865                }
5866                if (mBluetoothScanTimer != null) {
5867                    mBluetoothScanTimer.detach();
5868                    mBluetoothScanTimer = null;
5869                }
5870                if (mUserActivityCounters != null) {
5871                    for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5872                        mUserActivityCounters[i].detach();
5873                    }
5874                }
5875                if (mNetworkByteActivityCounters != null) {
5876                    for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5877                        mNetworkByteActivityCounters[i].detach();
5878                        mNetworkPacketActivityCounters[i].detach();
5879                    }
5880                }
5881
5882                if (mWifiControllerActivity != null) {
5883                    mWifiControllerActivity.detach();
5884                }
5885
5886                if (mBluetoothControllerActivity != null) {
5887                    mBluetoothControllerActivity.detach();
5888                }
5889
5890                if (mModemControllerActivity != null) {
5891                    mModemControllerActivity.detach();
5892                }
5893
5894                mPids.clear();
5895
5896                mUserCpuTime.detach();
5897                mSystemCpuTime.detach();
5898                mCpuPower.detach();
5899
5900                if (mCpuClusterSpeed != null) {
5901                    for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
5902                        if (cpuSpeeds != null) {
5903                            for (LongSamplingCounter c : cpuSpeeds) {
5904                                if (c != null) {
5905                                    c.detach();
5906                                }
5907                            }
5908                        }
5909                    }
5910                }
5911            }
5912
5913            return !active;
5914        }
5915
5916        void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
5917            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
5918            int NW = wakeStats.size();
5919            out.writeInt(NW);
5920            for (int iw=0; iw<NW; iw++) {
5921                out.writeString(wakeStats.keyAt(iw));
5922                Uid.Wakelock wakelock = wakeStats.valueAt(iw);
5923                wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
5924            }
5925
5926            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
5927            int NS = syncStats.size();
5928            out.writeInt(NS);
5929            for (int is=0; is<NS; is++) {
5930                out.writeString(syncStats.keyAt(is));
5931                StopwatchTimer timer = syncStats.valueAt(is);
5932                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
5933            }
5934
5935            final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
5936            int NJ = jobStats.size();
5937            out.writeInt(NJ);
5938            for (int ij=0; ij<NJ; ij++) {
5939                out.writeString(jobStats.keyAt(ij));
5940                StopwatchTimer timer = jobStats.valueAt(ij);
5941                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
5942            }
5943
5944            int NSE = mSensorStats.size();
5945            out.writeInt(NSE);
5946            for (int ise=0; ise<NSE; ise++) {
5947                out.writeInt(mSensorStats.keyAt(ise));
5948                Uid.Sensor sensor = mSensorStats.valueAt(ise);
5949                sensor.writeToParcelLocked(out, elapsedRealtimeUs);
5950            }
5951
5952            int NP = mProcessStats.size();
5953            out.writeInt(NP);
5954            for (int ip=0; ip<NP; ip++) {
5955                out.writeString(mProcessStats.keyAt(ip));
5956                Uid.Proc proc = mProcessStats.valueAt(ip);
5957                proc.writeToParcelLocked(out);
5958            }
5959
5960            out.writeInt(mPackageStats.size());
5961            for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
5962                out.writeString(pkgEntry.getKey());
5963                Uid.Pkg pkg = pkgEntry.getValue();
5964                pkg.writeToParcelLocked(out);
5965            }
5966
5967            if (mWifiRunningTimer != null) {
5968                out.writeInt(1);
5969                mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
5970            } else {
5971                out.writeInt(0);
5972            }
5973            if (mFullWifiLockTimer != null) {
5974                out.writeInt(1);
5975                mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
5976            } else {
5977                out.writeInt(0);
5978            }
5979            if (mWifiScanTimer != null) {
5980                out.writeInt(1);
5981                mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
5982            } else {
5983                out.writeInt(0);
5984            }
5985            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5986                if (mWifiBatchedScanTimer[i] != null) {
5987                    out.writeInt(1);
5988                    mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
5989                } else {
5990                    out.writeInt(0);
5991                }
5992            }
5993            if (mWifiMulticastTimer != null) {
5994                out.writeInt(1);
5995                mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
5996            } else {
5997                out.writeInt(0);
5998            }
5999
6000            if (mAudioTurnedOnTimer != null) {
6001                out.writeInt(1);
6002                mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6003            } else {
6004                out.writeInt(0);
6005            }
6006            if (mVideoTurnedOnTimer != null) {
6007                out.writeInt(1);
6008                mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6009            } else {
6010                out.writeInt(0);
6011            }
6012            if (mFlashlightTurnedOnTimer != null) {
6013                out.writeInt(1);
6014                mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6015            } else {
6016                out.writeInt(0);
6017            }
6018            if (mCameraTurnedOnTimer != null) {
6019                out.writeInt(1);
6020                mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
6021            } else {
6022                out.writeInt(0);
6023            }
6024            if (mForegroundActivityTimer != null) {
6025                out.writeInt(1);
6026                mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
6027            } else {
6028                out.writeInt(0);
6029            }
6030            if (mBluetoothScanTimer != null) {
6031                out.writeInt(1);
6032                mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
6033            } else {
6034                out.writeInt(0);
6035            }
6036            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
6037                if (mProcessStateTimer[i] != null) {
6038                    out.writeInt(1);
6039                    mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
6040                } else {
6041                    out.writeInt(0);
6042                }
6043            }
6044            if (mVibratorOnTimer != null) {
6045                out.writeInt(1);
6046                mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
6047            } else {
6048                out.writeInt(0);
6049            }
6050            if (mUserActivityCounters != null) {
6051                out.writeInt(1);
6052                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6053                    mUserActivityCounters[i].writeToParcel(out);
6054                }
6055            } else {
6056                out.writeInt(0);
6057            }
6058            if (mNetworkByteActivityCounters != null) {
6059                out.writeInt(1);
6060                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6061                    mNetworkByteActivityCounters[i].writeToParcel(out);
6062                    mNetworkPacketActivityCounters[i].writeToParcel(out);
6063                }
6064                mMobileRadioActiveTime.writeToParcel(out);
6065                mMobileRadioActiveCount.writeToParcel(out);
6066            } else {
6067                out.writeInt(0);
6068            }
6069
6070            if (mWifiControllerActivity != null) {
6071                out.writeInt(1);
6072                mWifiControllerActivity.writeToParcel(out, 0);
6073            } else {
6074                out.writeInt(0);
6075            }
6076
6077            if (mBluetoothControllerActivity != null) {
6078                out.writeInt(1);
6079                mBluetoothControllerActivity.writeToParcel(out, 0);
6080            } else {
6081                out.writeInt(0);
6082            }
6083
6084            if (mModemControllerActivity != null) {
6085                out.writeInt(1);
6086                mModemControllerActivity.writeToParcel(out, 0);
6087            } else {
6088                out.writeInt(0);
6089            }
6090
6091            mUserCpuTime.writeToParcel(out);
6092            mSystemCpuTime.writeToParcel(out);
6093            mCpuPower.writeToParcel(out);
6094
6095            if (mCpuClusterSpeed != null) {
6096                out.writeInt(1);
6097                out.writeInt(mCpuClusterSpeed.length);
6098                for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
6099                    if (cpuSpeeds != null) {
6100                        out.writeInt(1);
6101                        out.writeInt(cpuSpeeds.length);
6102                        for (LongSamplingCounter c : cpuSpeeds) {
6103                            if (c != null) {
6104                                out.writeInt(1);
6105                                c.writeToParcel(out);
6106                            } else {
6107                                out.writeInt(0);
6108                            }
6109                        }
6110                    } else {
6111                        out.writeInt(0);
6112                    }
6113                }
6114            } else {
6115                out.writeInt(0);
6116            }
6117        }
6118
6119        void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
6120            int numWakelocks = in.readInt();
6121            mWakelockStats.clear();
6122            for (int j = 0; j < numWakelocks; j++) {
6123                String wakelockName = in.readString();
6124                Uid.Wakelock wakelock = new Wakelock(mBsi, this);
6125                wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
6126                mWakelockStats.add(wakelockName, wakelock);
6127            }
6128
6129            int numSyncs = in.readInt();
6130            mSyncStats.clear();
6131            for (int j = 0; j < numSyncs; j++) {
6132                String syncName = in.readString();
6133                if (in.readInt() != 0) {
6134                    mSyncStats.add(syncName,
6135                            new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null, timeBase, in));
6136                }
6137            }
6138
6139            int numJobs = in.readInt();
6140            mJobStats.clear();
6141            for (int j = 0; j < numJobs; j++) {
6142                String jobName = in.readString();
6143                if (in.readInt() != 0) {
6144                    mJobStats.add(jobName, new StopwatchTimer(mBsi.mClocks, Uid.this, JOB, null,
6145                                timeBase, in));
6146                }
6147            }
6148
6149            int numSensors = in.readInt();
6150            mSensorStats.clear();
6151            for (int k = 0; k < numSensors; k++) {
6152                int sensorNumber = in.readInt();
6153                Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
6154                sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, in);
6155                mSensorStats.put(sensorNumber, sensor);
6156            }
6157
6158            int numProcs = in.readInt();
6159            mProcessStats.clear();
6160            for (int k = 0; k < numProcs; k++) {
6161                String processName = in.readString();
6162                Uid.Proc proc = new Proc(mBsi, processName);
6163                proc.readFromParcelLocked(in);
6164                mProcessStats.put(processName, proc);
6165            }
6166
6167            int numPkgs = in.readInt();
6168            mPackageStats.clear();
6169            for (int l = 0; l < numPkgs; l++) {
6170                String packageName = in.readString();
6171                Uid.Pkg pkg = new Pkg(mBsi);
6172                pkg.readFromParcelLocked(in);
6173                mPackageStats.put(packageName, pkg);
6174            }
6175
6176            mWifiRunning = false;
6177            if (in.readInt() != 0) {
6178                mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
6179                        mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
6180            } else {
6181                mWifiRunningTimer = null;
6182            }
6183            mFullWifiLockOut = false;
6184            if (in.readInt() != 0) {
6185                mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
6186                        mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
6187            } else {
6188                mFullWifiLockTimer = null;
6189            }
6190            mWifiScanStarted = false;
6191            if (in.readInt() != 0) {
6192                mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
6193                        mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, in);
6194            } else {
6195                mWifiScanTimer = null;
6196            }
6197            mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
6198            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
6199                if (in.readInt() != 0) {
6200                    makeWifiBatchedScanBin(i, in);
6201                } else {
6202                    mWifiBatchedScanTimer[i] = null;
6203                }
6204            }
6205            mWifiMulticastEnabled = false;
6206            if (in.readInt() != 0) {
6207                mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
6208                        mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
6209            } else {
6210                mWifiMulticastTimer = null;
6211            }
6212            if (in.readInt() != 0) {
6213                mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
6214                        mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6215            } else {
6216                mAudioTurnedOnTimer = null;
6217            }
6218            if (in.readInt() != 0) {
6219                mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
6220                        mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6221            } else {
6222                mVideoTurnedOnTimer = null;
6223            }
6224            if (in.readInt() != 0) {
6225                mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6226                        FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6227            } else {
6228                mFlashlightTurnedOnTimer = null;
6229            }
6230            if (in.readInt() != 0) {
6231                mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
6232                        mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
6233            } else {
6234                mCameraTurnedOnTimer = null;
6235            }
6236            if (in.readInt() != 0) {
6237                mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
6238                        FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
6239            } else {
6240                mForegroundActivityTimer = null;
6241            }
6242            if (in.readInt() != 0) {
6243                mBluetoothScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
6244                        mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase, in);
6245            } else {
6246                mBluetoothScanTimer = null;
6247            }
6248            mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
6249            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
6250                if (in.readInt() != 0) {
6251                    makeProcessState(i, in);
6252                } else {
6253                    mProcessStateTimer[i] = null;
6254                }
6255            }
6256            if (in.readInt() != 0) {
6257                mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
6258                        mBsi.mOnBatteryTimeBase, in);
6259            } else {
6260                mVibratorOnTimer = null;
6261            }
6262            if (in.readInt() != 0) {
6263                mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
6264                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
6265                    mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
6266                }
6267            } else {
6268                mUserActivityCounters = null;
6269            }
6270            if (in.readInt() != 0) {
6271                mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6272                mNetworkPacketActivityCounters
6273                        = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
6274                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6275                    mNetworkByteActivityCounters[i]
6276                            = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6277                    mNetworkPacketActivityCounters[i]
6278                            = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6279                }
6280                mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6281                mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6282            } else {
6283                mNetworkByteActivityCounters = null;
6284                mNetworkPacketActivityCounters = null;
6285            }
6286
6287            if (in.readInt() != 0) {
6288                mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6289                        NUM_WIFI_TX_LEVELS, in);
6290            } else {
6291                mWifiControllerActivity = null;
6292            }
6293
6294            if (in.readInt() != 0) {
6295                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6296                        NUM_BT_TX_LEVELS, in);
6297            } else {
6298                mBluetoothControllerActivity = null;
6299            }
6300
6301            if (in.readInt() != 0) {
6302                mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
6303                        ModemActivityInfo.TX_POWER_LEVELS, in);
6304            } else {
6305                mModemControllerActivity = null;
6306            }
6307
6308            mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6309            mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6310            mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6311
6312            if (in.readInt() != 0) {
6313                int numCpuClusters = in.readInt();
6314                if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
6315                    throw new ParcelFormatException("Incompatible number of cpu clusters");
6316                }
6317
6318                mCpuClusterSpeed = new LongSamplingCounter[numCpuClusters][];
6319                for (int cluster = 0; cluster < numCpuClusters; cluster++) {
6320                    if (in.readInt() != 0) {
6321                        int numSpeeds = in.readInt();
6322                        if (mBsi.mPowerProfile != null &&
6323                                mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
6324                            throw new ParcelFormatException("Incompatible number of cpu speeds");
6325                        }
6326
6327                        final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
6328                        mCpuClusterSpeed[cluster] = cpuSpeeds;
6329                        for (int speed = 0; speed < numSpeeds; speed++) {
6330                            if (in.readInt() != 0) {
6331                                cpuSpeeds[speed] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
6332                            }
6333                        }
6334                    } else {
6335                        mCpuClusterSpeed[cluster] = null;
6336                    }
6337                }
6338            } else {
6339                mCpuClusterSpeed = null;
6340            }
6341        }
6342
6343        /**
6344         * The statistics associated with a particular wake lock.
6345         */
6346        public static class Wakelock extends BatteryStats.Uid.Wakelock {
6347            /**
6348             * BatteryStatsImpl that we are associated with.
6349             */
6350            protected BatteryStatsImpl mBsi;
6351
6352            /**
6353             * BatteryStatsImpl that we are associated with.
6354             */
6355            protected Uid mUid;
6356
6357            /**
6358             * How long (in ms) this uid has been keeping the device partially awake.
6359             */
6360            StopwatchTimer mTimerPartial;
6361
6362            /**
6363             * How long (in ms) this uid has been keeping the device fully awake.
6364             */
6365            StopwatchTimer mTimerFull;
6366
6367            /**
6368             * How long (in ms) this uid has had a window keeping the device awake.
6369             */
6370            StopwatchTimer mTimerWindow;
6371
6372            /**
6373             * How long (in ms) this uid has had a draw wake lock.
6374             */
6375            StopwatchTimer mTimerDraw;
6376
6377            public Wakelock(BatteryStatsImpl bsi, Uid uid) {
6378                mBsi = bsi;
6379                mUid = uid;
6380            }
6381
6382            /**
6383             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
6384             * proper timer pool from the given BatteryStatsImpl object.
6385             *
6386             * @param in the Parcel to be read from.
6387             * return a new Timer, or null.
6388             */
6389            private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
6390                    TimeBase timeBase, Parcel in) {
6391                if (in.readInt() == 0) {
6392                    return null;
6393                }
6394
6395                return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
6396            }
6397
6398            boolean reset() {
6399                boolean wlactive = false;
6400                if (mTimerFull != null) {
6401                    wlactive |= !mTimerFull.reset(false);
6402                }
6403                if (mTimerPartial != null) {
6404                    wlactive |= !mTimerPartial.reset(false);
6405                }
6406                if (mTimerWindow != null) {
6407                    wlactive |= !mTimerWindow.reset(false);
6408                }
6409                if (mTimerDraw != null) {
6410                    wlactive |= !mTimerDraw.reset(false);
6411                }
6412                if (!wlactive) {
6413                    if (mTimerFull != null) {
6414                        mTimerFull.detach();
6415                        mTimerFull = null;
6416                    }
6417                    if (mTimerPartial != null) {
6418                        mTimerPartial.detach();
6419                        mTimerPartial = null;
6420                    }
6421                    if (mTimerWindow != null) {
6422                        mTimerWindow.detach();
6423                        mTimerWindow = null;
6424                    }
6425                    if (mTimerDraw != null) {
6426                        mTimerDraw.detach();
6427                        mTimerDraw = null;
6428                    }
6429                }
6430                return !wlactive;
6431            }
6432
6433            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
6434                mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
6435                        mBsi.mPartialTimers, screenOffTimeBase, in);
6436                mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, mBsi.mFullTimers, timeBase, in);
6437                mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, mBsi.mWindowTimers, timeBase, in);
6438                mTimerDraw = readTimerFromParcel(WAKE_TYPE_DRAW, mBsi.mDrawTimers, timeBase, in);
6439            }
6440
6441            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
6442                Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
6443                Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
6444                Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
6445                Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
6446            }
6447
6448            @Override
6449            public Timer getWakeTime(int type) {
6450                switch (type) {
6451                case WAKE_TYPE_FULL: return mTimerFull;
6452                case WAKE_TYPE_PARTIAL: return mTimerPartial;
6453                case WAKE_TYPE_WINDOW: return mTimerWindow;
6454                case WAKE_TYPE_DRAW: return mTimerDraw;
6455                default: throw new IllegalArgumentException("type = " + type);
6456                }
6457            }
6458
6459            public StopwatchTimer getStopwatchTimer(int type) {
6460                StopwatchTimer t;
6461                switch (type) {
6462                    case WAKE_TYPE_PARTIAL:
6463                        t = mTimerPartial;
6464                        if (t == null) {
6465                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL,
6466                                    mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase);
6467                            mTimerPartial = t;
6468                        }
6469                        return t;
6470                    case WAKE_TYPE_FULL:
6471                        t = mTimerFull;
6472                        if (t == null) {
6473                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL,
6474                                    mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
6475                            mTimerFull = t;
6476                        }
6477                        return t;
6478                    case WAKE_TYPE_WINDOW:
6479                        t = mTimerWindow;
6480                        if (t == null) {
6481                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW,
6482                                    mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
6483                            mTimerWindow = t;
6484                        }
6485                        return t;
6486                    case WAKE_TYPE_DRAW:
6487                        t = mTimerDraw;
6488                        if (t == null) {
6489                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW,
6490                                    mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
6491                            mTimerDraw = t;
6492                        }
6493                        return t;
6494                    default:
6495                        throw new IllegalArgumentException("type=" + type);
6496                }
6497            }
6498        }
6499
6500        public static class Sensor extends BatteryStats.Uid.Sensor {
6501            /**
6502             * BatteryStatsImpl that we are associated with.
6503             */
6504            protected BatteryStatsImpl mBsi;
6505
6506            /**
6507             * BatteryStatsImpl that we are associated with.
6508             */
6509            protected Uid mUid;
6510
6511            final int mHandle;
6512            StopwatchTimer mTimer;
6513
6514            public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
6515                mBsi = bsi;
6516                mUid = uid;
6517                mHandle = handle;
6518            }
6519
6520            private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) {
6521                if (in.readInt() == 0) {
6522                    return null;
6523                }
6524
6525                ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
6526                if (pool == null) {
6527                    pool = new ArrayList<StopwatchTimer>();
6528                    mBsi.mSensorTimers.put(mHandle, pool);
6529                }
6530                return new StopwatchTimer(mBsi.mClocks, mUid, 0, pool, timeBase, in);
6531            }
6532
6533            boolean reset() {
6534                if (mTimer.reset(true)) {
6535                    mTimer = null;
6536                    return true;
6537                }
6538                return false;
6539            }
6540
6541            void readFromParcelLocked(TimeBase timeBase, Parcel in) {
6542                mTimer = readTimerFromParcel(timeBase, in);
6543            }
6544
6545            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
6546                Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
6547            }
6548
6549            @Override
6550            public Timer getSensorTime() {
6551                return mTimer;
6552            }
6553
6554            @Override
6555            public int getHandle() {
6556                return mHandle;
6557            }
6558        }
6559
6560        /**
6561         * The statistics associated with a particular process.
6562         */
6563        public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
6564            /**
6565             * BatteryStatsImpl that we are associated with.
6566             */
6567            protected BatteryStatsImpl mBsi;
6568
6569            /**
6570             * The name of this process.
6571             */
6572            final String mName;
6573
6574            /**
6575             * Remains true until removed from the stats.
6576             */
6577            boolean mActive = true;
6578
6579            /**
6580             * Total time (in ms) spent executing in user code.
6581             */
6582            long mUserTime;
6583
6584            /**
6585             * Total time (in ms) spent executing in kernel code.
6586             */
6587            long mSystemTime;
6588
6589            /**
6590             * Amount of time (in ms) the process was running in the foreground.
6591             */
6592            long mForegroundTime;
6593
6594            /**
6595             * Number of times the process has been started.
6596             */
6597            int mStarts;
6598
6599            /**
6600             * Number of times the process has crashed.
6601             */
6602            int mNumCrashes;
6603
6604            /**
6605             * Number of times the process has had an ANR.
6606             */
6607            int mNumAnrs;
6608
6609            /**
6610             * The amount of user time loaded from a previous save.
6611             */
6612            long mLoadedUserTime;
6613
6614            /**
6615             * The amount of system time loaded from a previous save.
6616             */
6617            long mLoadedSystemTime;
6618
6619            /**
6620             * The amount of foreground time loaded from a previous save.
6621             */
6622            long mLoadedForegroundTime;
6623
6624            /**
6625             * The number of times the process has started from a previous save.
6626             */
6627            int mLoadedStarts;
6628
6629            /**
6630             * Number of times the process has crashed from a previous save.
6631             */
6632            int mLoadedNumCrashes;
6633
6634            /**
6635             * Number of times the process has had an ANR from a previous save.
6636             */
6637            int mLoadedNumAnrs;
6638
6639            /**
6640             * The amount of user time when last unplugged.
6641             */
6642            long mUnpluggedUserTime;
6643
6644            /**
6645             * The amount of system time when last unplugged.
6646             */
6647            long mUnpluggedSystemTime;
6648
6649            /**
6650             * The amount of foreground time since unplugged.
6651             */
6652            long mUnpluggedForegroundTime;
6653
6654            /**
6655             * The number of times the process has started before unplugged.
6656             */
6657            int mUnpluggedStarts;
6658
6659            /**
6660             * Number of times the process has crashed before unplugged.
6661             */
6662            int mUnpluggedNumCrashes;
6663
6664            /**
6665             * Number of times the process has had an ANR before unplugged.
6666             */
6667            int mUnpluggedNumAnrs;
6668
6669            ArrayList<ExcessivePower> mExcessivePower;
6670
6671            public Proc(BatteryStatsImpl bsi, String name) {
6672                mBsi = bsi;
6673                mName = name;
6674                mBsi.mOnBatteryTimeBase.add(this);
6675            }
6676
6677            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
6678                mUnpluggedUserTime = mUserTime;
6679                mUnpluggedSystemTime = mSystemTime;
6680                mUnpluggedForegroundTime = mForegroundTime;
6681                mUnpluggedStarts = mStarts;
6682                mUnpluggedNumCrashes = mNumCrashes;
6683                mUnpluggedNumAnrs = mNumAnrs;
6684            }
6685
6686            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
6687            }
6688
6689            void detach() {
6690                mActive = false;
6691                mBsi.mOnBatteryTimeBase.remove(this);
6692            }
6693
6694            public int countExcessivePowers() {
6695                return mExcessivePower != null ? mExcessivePower.size() : 0;
6696            }
6697
6698            public ExcessivePower getExcessivePower(int i) {
6699                if (mExcessivePower != null) {
6700                    return mExcessivePower.get(i);
6701                }
6702                return null;
6703            }
6704
6705            public void addExcessiveWake(long overTime, long usedTime) {
6706                if (mExcessivePower == null) {
6707                    mExcessivePower = new ArrayList<ExcessivePower>();
6708                }
6709                ExcessivePower ew = new ExcessivePower();
6710                ew.type = ExcessivePower.TYPE_WAKE;
6711                ew.overTime = overTime;
6712                ew.usedTime = usedTime;
6713                mExcessivePower.add(ew);
6714            }
6715
6716            public void addExcessiveCpu(long overTime, long usedTime) {
6717                if (mExcessivePower == null) {
6718                    mExcessivePower = new ArrayList<ExcessivePower>();
6719                }
6720                ExcessivePower ew = new ExcessivePower();
6721                ew.type = ExcessivePower.TYPE_CPU;
6722                ew.overTime = overTime;
6723                ew.usedTime = usedTime;
6724                mExcessivePower.add(ew);
6725            }
6726
6727            void writeExcessivePowerToParcelLocked(Parcel out) {
6728                if (mExcessivePower == null) {
6729                    out.writeInt(0);
6730                    return;
6731                }
6732
6733                final int N = mExcessivePower.size();
6734                out.writeInt(N);
6735                for (int i=0; i<N; i++) {
6736                    ExcessivePower ew = mExcessivePower.get(i);
6737                    out.writeInt(ew.type);
6738                    out.writeLong(ew.overTime);
6739                    out.writeLong(ew.usedTime);
6740                }
6741            }
6742
6743            void readExcessivePowerFromParcelLocked(Parcel in) {
6744                final int N = in.readInt();
6745                if (N == 0) {
6746                    mExcessivePower = null;
6747                    return;
6748                }
6749
6750                if (N > 10000) {
6751                    throw new ParcelFormatException(
6752                            "File corrupt: too many excessive power entries " + N);
6753                }
6754
6755                mExcessivePower = new ArrayList<>();
6756                for (int i=0; i<N; i++) {
6757                    ExcessivePower ew = new ExcessivePower();
6758                    ew.type = in.readInt();
6759                    ew.overTime = in.readLong();
6760                    ew.usedTime = in.readLong();
6761                    mExcessivePower.add(ew);
6762                }
6763            }
6764
6765            void writeToParcelLocked(Parcel out) {
6766                out.writeLong(mUserTime);
6767                out.writeLong(mSystemTime);
6768                out.writeLong(mForegroundTime);
6769                out.writeInt(mStarts);
6770                out.writeInt(mNumCrashes);
6771                out.writeInt(mNumAnrs);
6772                out.writeLong(mLoadedUserTime);
6773                out.writeLong(mLoadedSystemTime);
6774                out.writeLong(mLoadedForegroundTime);
6775                out.writeInt(mLoadedStarts);
6776                out.writeInt(mLoadedNumCrashes);
6777                out.writeInt(mLoadedNumAnrs);
6778                out.writeLong(mUnpluggedUserTime);
6779                out.writeLong(mUnpluggedSystemTime);
6780                out.writeLong(mUnpluggedForegroundTime);
6781                out.writeInt(mUnpluggedStarts);
6782                out.writeInt(mUnpluggedNumCrashes);
6783                out.writeInt(mUnpluggedNumAnrs);
6784                writeExcessivePowerToParcelLocked(out);
6785            }
6786
6787            void readFromParcelLocked(Parcel in) {
6788                mUserTime = in.readLong();
6789                mSystemTime = in.readLong();
6790                mForegroundTime = in.readLong();
6791                mStarts = in.readInt();
6792                mNumCrashes = in.readInt();
6793                mNumAnrs = in.readInt();
6794                mLoadedUserTime = in.readLong();
6795                mLoadedSystemTime = in.readLong();
6796                mLoadedForegroundTime = in.readLong();
6797                mLoadedStarts = in.readInt();
6798                mLoadedNumCrashes = in.readInt();
6799                mLoadedNumAnrs = in.readInt();
6800                mUnpluggedUserTime = in.readLong();
6801                mUnpluggedSystemTime = in.readLong();
6802                mUnpluggedForegroundTime = in.readLong();
6803                mUnpluggedStarts = in.readInt();
6804                mUnpluggedNumCrashes = in.readInt();
6805                mUnpluggedNumAnrs = in.readInt();
6806                readExcessivePowerFromParcelLocked(in);
6807            }
6808
6809            public void addCpuTimeLocked(int utime, int stime) {
6810                mUserTime += utime;
6811                mSystemTime += stime;
6812            }
6813
6814            public void addForegroundTimeLocked(long ttime) {
6815                mForegroundTime += ttime;
6816            }
6817
6818            public void incStartsLocked() {
6819                mStarts++;
6820            }
6821
6822            public void incNumCrashesLocked() {
6823                mNumCrashes++;
6824            }
6825
6826            public void incNumAnrsLocked() {
6827                mNumAnrs++;
6828            }
6829
6830            @Override
6831            public boolean isActive() {
6832                return mActive;
6833            }
6834
6835            @Override
6836            public long getUserTime(int which) {
6837                long val = mUserTime;
6838                if (which == STATS_CURRENT) {
6839                    val -= mLoadedUserTime;
6840                } else if (which == STATS_SINCE_UNPLUGGED) {
6841                    val -= mUnpluggedUserTime;
6842                }
6843                return val;
6844            }
6845
6846            @Override
6847            public long getSystemTime(int which) {
6848                long val = mSystemTime;
6849                if (which == STATS_CURRENT) {
6850                    val -= mLoadedSystemTime;
6851                } else if (which == STATS_SINCE_UNPLUGGED) {
6852                    val -= mUnpluggedSystemTime;
6853                }
6854                return val;
6855            }
6856
6857            @Override
6858            public long getForegroundTime(int which) {
6859                long val = mForegroundTime;
6860                if (which == STATS_CURRENT) {
6861                    val -= mLoadedForegroundTime;
6862                } else if (which == STATS_SINCE_UNPLUGGED) {
6863                    val -= mUnpluggedForegroundTime;
6864                }
6865                return val;
6866            }
6867
6868            @Override
6869            public int getStarts(int which) {
6870                int val = mStarts;
6871                if (which == STATS_CURRENT) {
6872                    val -= mLoadedStarts;
6873                } else if (which == STATS_SINCE_UNPLUGGED) {
6874                    val -= mUnpluggedStarts;
6875                }
6876                return val;
6877            }
6878
6879            @Override
6880            public int getNumCrashes(int which) {
6881                int val = mNumCrashes;
6882                if (which == STATS_CURRENT) {
6883                    val -= mLoadedNumCrashes;
6884                } else if (which == STATS_SINCE_UNPLUGGED) {
6885                    val -= mUnpluggedNumCrashes;
6886                }
6887                return val;
6888            }
6889
6890            @Override
6891            public int getNumAnrs(int which) {
6892                int val = mNumAnrs;
6893                if (which == STATS_CURRENT) {
6894                    val -= mLoadedNumAnrs;
6895                } else if (which == STATS_SINCE_UNPLUGGED) {
6896                    val -= mUnpluggedNumAnrs;
6897                }
6898                return val;
6899            }
6900        }
6901
6902        /**
6903         * The statistics associated with a particular package.
6904         */
6905        public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
6906            /**
6907             * BatteryStatsImpl that we are associated with.
6908             */
6909            protected BatteryStatsImpl mBsi;
6910
6911            /**
6912             * Number of times wakeup alarms have occurred for this app.
6913             */
6914            ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
6915
6916            /**
6917             * The statics we have collected for this package's services.
6918             */
6919            final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
6920
6921            public Pkg(BatteryStatsImpl bsi) {
6922                mBsi = bsi;
6923                mBsi.mOnBatteryScreenOffTimeBase.add(this);
6924            }
6925
6926            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
6927            }
6928
6929            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
6930            }
6931
6932            void detach() {
6933                mBsi.mOnBatteryScreenOffTimeBase.remove(this);
6934            }
6935
6936            void readFromParcelLocked(Parcel in) {
6937                int numWA = in.readInt();
6938                mWakeupAlarms.clear();
6939                for (int i=0; i<numWA; i++) {
6940                    String tag = in.readString();
6941                    mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryTimeBase, in));
6942                }
6943
6944                int numServs = in.readInt();
6945                mServiceStats.clear();
6946                for (int m = 0; m < numServs; m++) {
6947                    String serviceName = in.readString();
6948                    Uid.Pkg.Serv serv = new Serv(mBsi);
6949                    mServiceStats.put(serviceName, serv);
6950
6951                    serv.readFromParcelLocked(in);
6952                }
6953            }
6954
6955            void writeToParcelLocked(Parcel out) {
6956                int numWA = mWakeupAlarms.size();
6957                out.writeInt(numWA);
6958                for (int i=0; i<numWA; i++) {
6959                    out.writeString(mWakeupAlarms.keyAt(i));
6960                    mWakeupAlarms.valueAt(i).writeToParcel(out);
6961                }
6962
6963                final int NS = mServiceStats.size();
6964                out.writeInt(NS);
6965                for (int i=0; i<NS; i++) {
6966                    out.writeString(mServiceStats.keyAt(i));
6967                    Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
6968                    serv.writeToParcelLocked(out);
6969                }
6970            }
6971
6972            @Override
6973            public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
6974                return mWakeupAlarms;
6975            }
6976
6977            public void noteWakeupAlarmLocked(String tag) {
6978                Counter c = mWakeupAlarms.get(tag);
6979                if (c == null) {
6980                    c = new Counter(mBsi.mOnBatteryTimeBase);
6981                    mWakeupAlarms.put(tag, c);
6982                }
6983                c.stepAtomic();
6984            }
6985
6986            @Override
6987            public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
6988                return mServiceStats;
6989            }
6990
6991            /**
6992             * The statistics associated with a particular service.
6993             */
6994            public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
6995                /**
6996                 * BatteryStatsImpl that we are associated with.
6997                 */
6998                protected BatteryStatsImpl mBsi;
6999
7000                /**
7001                 * The android package in which this service resides.
7002                 */
7003                protected Pkg mPkg;
7004
7005                /**
7006                 * Total time (ms in battery uptime) the service has been left started.
7007                 */
7008                protected long mStartTime;
7009
7010                /**
7011                 * If service has been started and not yet stopped, this is
7012                 * when it was started.
7013                 */
7014                protected long mRunningSince;
7015
7016                /**
7017                 * True if we are currently running.
7018                 */
7019                protected boolean mRunning;
7020
7021                /**
7022                 * Total number of times startService() has been called.
7023                 */
7024                protected int mStarts;
7025
7026                /**
7027                 * Total time (ms in battery uptime) the service has been left launched.
7028                 */
7029                protected long mLaunchedTime;
7030
7031                /**
7032                 * If service has been launched and not yet exited, this is
7033                 * when it was launched (ms in battery uptime).
7034                 */
7035                protected long mLaunchedSince;
7036
7037                /**
7038                 * True if we are currently launched.
7039                 */
7040                protected boolean mLaunched;
7041
7042                /**
7043                 * Total number times the service has been launched.
7044                 */
7045                protected int mLaunches;
7046
7047                /**
7048                 * The amount of time spent started loaded from a previous save
7049                 * (ms in battery uptime).
7050                 */
7051                protected long mLoadedStartTime;
7052
7053                /**
7054                 * The number of starts loaded from a previous save.
7055                 */
7056                protected int mLoadedStarts;
7057
7058                /**
7059                 * The number of launches loaded from a previous save.
7060                 */
7061                protected int mLoadedLaunches;
7062
7063                /**
7064                 * The amount of time spent started as of the last run (ms
7065                 * in battery uptime).
7066                 */
7067                protected long mLastStartTime;
7068
7069                /**
7070                 * The number of starts as of the last run.
7071                 */
7072                protected int mLastStarts;
7073
7074                /**
7075                 * The number of launches as of the last run.
7076                 */
7077                protected int mLastLaunches;
7078
7079                /**
7080                 * The amount of time spent started when last unplugged (ms
7081                 * in battery uptime).
7082                 */
7083                protected long mUnpluggedStartTime;
7084
7085                /**
7086                 * The number of starts when last unplugged.
7087                 */
7088                protected int mUnpluggedStarts;
7089
7090                /**
7091                 * The number of launches when last unplugged.
7092                 */
7093                protected int mUnpluggedLaunches;
7094
7095                /**
7096                 * Construct a Serv. Also adds it to the on-battery time base as a listener.
7097                 */
7098                public Serv(BatteryStatsImpl bsi) {
7099                    mBsi = bsi;
7100                    mBsi.mOnBatteryTimeBase.add(this);
7101                }
7102
7103                public void onTimeStarted(long elapsedRealtime, long baseUptime,
7104                        long baseRealtime) {
7105                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
7106                    mUnpluggedStarts = mStarts;
7107                    mUnpluggedLaunches = mLaunches;
7108                }
7109
7110                public void onTimeStopped(long elapsedRealtime, long baseUptime,
7111                        long baseRealtime) {
7112                }
7113
7114                /**
7115                 * Remove this Serv as a listener from the time base.
7116                 */
7117                public void detach() {
7118                    mBsi.mOnBatteryTimeBase.remove(this);
7119                }
7120
7121                public void readFromParcelLocked(Parcel in) {
7122                    mStartTime = in.readLong();
7123                    mRunningSince = in.readLong();
7124                    mRunning = in.readInt() != 0;
7125                    mStarts = in.readInt();
7126                    mLaunchedTime = in.readLong();
7127                    mLaunchedSince = in.readLong();
7128                    mLaunched = in.readInt() != 0;
7129                    mLaunches = in.readInt();
7130                    mLoadedStartTime = in.readLong();
7131                    mLoadedStarts = in.readInt();
7132                    mLoadedLaunches = in.readInt();
7133                    mLastStartTime = 0;
7134                    mLastStarts = 0;
7135                    mLastLaunches = 0;
7136                    mUnpluggedStartTime = in.readLong();
7137                    mUnpluggedStarts = in.readInt();
7138                    mUnpluggedLaunches = in.readInt();
7139                }
7140
7141                public void writeToParcelLocked(Parcel out) {
7142                    out.writeLong(mStartTime);
7143                    out.writeLong(mRunningSince);
7144                    out.writeInt(mRunning ? 1 : 0);
7145                    out.writeInt(mStarts);
7146                    out.writeLong(mLaunchedTime);
7147                    out.writeLong(mLaunchedSince);
7148                    out.writeInt(mLaunched ? 1 : 0);
7149                    out.writeInt(mLaunches);
7150                    out.writeLong(mLoadedStartTime);
7151                    out.writeInt(mLoadedStarts);
7152                    out.writeInt(mLoadedLaunches);
7153                    out.writeLong(mUnpluggedStartTime);
7154                    out.writeInt(mUnpluggedStarts);
7155                    out.writeInt(mUnpluggedLaunches);
7156                }
7157
7158                public long getLaunchTimeToNowLocked(long batteryUptime) {
7159                    if (!mLaunched) return mLaunchedTime;
7160                    return mLaunchedTime + batteryUptime - mLaunchedSince;
7161                }
7162
7163                public long getStartTimeToNowLocked(long batteryUptime) {
7164                    if (!mRunning) return mStartTime;
7165                    return mStartTime + batteryUptime - mRunningSince;
7166                }
7167
7168                public void startLaunchedLocked() {
7169                    if (!mLaunched) {
7170                        mLaunches++;
7171                        mLaunchedSince = mBsi.getBatteryUptimeLocked();
7172                        mLaunched = true;
7173                    }
7174                }
7175
7176                public void stopLaunchedLocked() {
7177                    if (mLaunched) {
7178                        long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
7179                        if (time > 0) {
7180                            mLaunchedTime += time;
7181                        } else {
7182                            mLaunches--;
7183                        }
7184                        mLaunched = false;
7185                    }
7186                }
7187
7188                public void startRunningLocked() {
7189                    if (!mRunning) {
7190                        mStarts++;
7191                        mRunningSince = mBsi.getBatteryUptimeLocked();
7192                        mRunning = true;
7193                    }
7194                }
7195
7196                public void stopRunningLocked() {
7197                    if (mRunning) {
7198                        long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
7199                        if (time > 0) {
7200                            mStartTime += time;
7201                        } else {
7202                            mStarts--;
7203                        }
7204                        mRunning = false;
7205                    }
7206                }
7207
7208                public BatteryStatsImpl getBatteryStats() {
7209                    return mBsi;
7210                }
7211
7212                @Override
7213                public int getLaunches(int which) {
7214                    int val = mLaunches;
7215                    if (which == STATS_CURRENT) {
7216                        val -= mLoadedLaunches;
7217                    } else if (which == STATS_SINCE_UNPLUGGED) {
7218                        val -= mUnpluggedLaunches;
7219                    }
7220                    return val;
7221                }
7222
7223                @Override
7224                public long getStartTime(long now, int which) {
7225                    long val = getStartTimeToNowLocked(now);
7226                    if (which == STATS_CURRENT) {
7227                        val -= mLoadedStartTime;
7228                    } else if (which == STATS_SINCE_UNPLUGGED) {
7229                        val -= mUnpluggedStartTime;
7230                    }
7231                    return val;
7232                }
7233
7234                @Override
7235                public int getStarts(int which) {
7236                    int val = mStarts;
7237                    if (which == STATS_CURRENT) {
7238                        val -= mLoadedStarts;
7239                    } else if (which == STATS_SINCE_UNPLUGGED) {
7240                        val -= mUnpluggedStarts;
7241                    }
7242
7243                    return val;
7244                }
7245            }
7246
7247            final Serv newServiceStatsLocked() {
7248                return new Serv(mBsi);
7249            }
7250        }
7251
7252        /**
7253         * Retrieve the statistics object for a particular process, creating
7254         * if needed.
7255         */
7256        public Proc getProcessStatsLocked(String name) {
7257            Proc ps = mProcessStats.get(name);
7258            if (ps == null) {
7259                ps = new Proc(mBsi, name);
7260                mProcessStats.put(name, ps);
7261            }
7262
7263            return ps;
7264        }
7265
7266        public void updateUidProcessStateLocked(int procState) {
7267            int uidRunningState;
7268            if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
7269                uidRunningState = ActivityManager.PROCESS_STATE_NONEXISTENT;
7270            } else if (procState == ActivityManager.PROCESS_STATE_TOP) {
7271                uidRunningState = PROCESS_STATE_TOP;
7272            } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
7273                // Persistent and other foreground states go here.
7274                uidRunningState = PROCESS_STATE_FOREGROUND_SERVICE;
7275            } else if (procState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
7276                uidRunningState = PROCESS_STATE_TOP_SLEEPING;
7277            } else if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
7278                // Persistent and other foreground states go here.
7279                uidRunningState = PROCESS_STATE_FOREGROUND;
7280            } else if (procState <= ActivityManager.PROCESS_STATE_RECEIVER) {
7281                uidRunningState = PROCESS_STATE_BACKGROUND;
7282            } else {
7283                uidRunningState = PROCESS_STATE_CACHED;
7284            }
7285
7286            if (mProcessState == uidRunningState) return;
7287
7288            final long elapsedRealtime = mBsi.mClocks.elapsedRealtime();
7289
7290            if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
7291                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtime);
7292            }
7293            mProcessState = uidRunningState;
7294            if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
7295                if (mProcessStateTimer[uidRunningState] == null) {
7296                    makeProcessState(uidRunningState, null);
7297                }
7298                mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtime);
7299            }
7300        }
7301
7302        public SparseArray<? extends Pid> getPidStats() {
7303            return mPids;
7304        }
7305
7306        public Pid getPidStatsLocked(int pid) {
7307            Pid p = mPids.get(pid);
7308            if (p == null) {
7309                p = new Pid();
7310                mPids.put(pid, p);
7311            }
7312            return p;
7313        }
7314
7315        /**
7316         * Retrieve the statistics object for a particular service, creating
7317         * if needed.
7318         */
7319        public Pkg getPackageStatsLocked(String name) {
7320            Pkg ps = mPackageStats.get(name);
7321            if (ps == null) {
7322                ps = new Pkg(mBsi);
7323                mPackageStats.put(name, ps);
7324            }
7325
7326            return ps;
7327        }
7328
7329        /**
7330         * Retrieve the statistics object for a particular service, creating
7331         * if needed.
7332         */
7333        public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
7334            Pkg ps = getPackageStatsLocked(pkg);
7335            Pkg.Serv ss = ps.mServiceStats.get(serv);
7336            if (ss == null) {
7337                ss = ps.newServiceStatsLocked();
7338                ps.mServiceStats.put(serv, ss);
7339            }
7340
7341            return ss;
7342        }
7343
7344        public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
7345            StopwatchTimer timer = mSyncStats.instantiateObject();
7346            timer.readSummaryFromParcelLocked(in);
7347            mSyncStats.add(name, timer);
7348        }
7349
7350        public void readJobSummaryFromParcelLocked(String name, Parcel in) {
7351            StopwatchTimer timer = mJobStats.instantiateObject();
7352            timer.readSummaryFromParcelLocked(in);
7353            mJobStats.add(name, timer);
7354        }
7355
7356        public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
7357            Wakelock wl = new Wakelock(mBsi, this);
7358            mWakelockStats.add(wlName, wl);
7359            if (in.readInt() != 0) {
7360                wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
7361            }
7362            if (in.readInt() != 0) {
7363                wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
7364            }
7365            if (in.readInt() != 0) {
7366                wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
7367            }
7368            if (in.readInt() != 0) {
7369                wl.getStopwatchTimer(WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
7370            }
7371        }
7372
7373        public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
7374            Sensor se = mSensorStats.get(sensor);
7375            if (se == null) {
7376                if (!create) {
7377                    return null;
7378                }
7379                se = new Sensor(mBsi, this, sensor);
7380                mSensorStats.put(sensor, se);
7381            }
7382            StopwatchTimer t = se.mTimer;
7383            if (t != null) {
7384                return t;
7385            }
7386            ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
7387            if (timers == null) {
7388                timers = new ArrayList<StopwatchTimer>();
7389                mBsi.mSensorTimers.put(sensor, timers);
7390            }
7391            t = new StopwatchTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
7392                    mBsi.mOnBatteryTimeBase);
7393            se.mTimer = t;
7394            return t;
7395        }
7396
7397        public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
7398            StopwatchTimer t = mSyncStats.startObject(name);
7399            if (t != null) {
7400                t.startRunningLocked(elapsedRealtimeMs);
7401            }
7402        }
7403
7404        public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
7405            StopwatchTimer t = mSyncStats.stopObject(name);
7406            if (t != null) {
7407                t.stopRunningLocked(elapsedRealtimeMs);
7408            }
7409        }
7410
7411        public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
7412            StopwatchTimer t = mJobStats.startObject(name);
7413            if (t != null) {
7414                t.startRunningLocked(elapsedRealtimeMs);
7415            }
7416        }
7417
7418        public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
7419            StopwatchTimer t = mJobStats.stopObject(name);
7420            if (t != null) {
7421                t.stopRunningLocked(elapsedRealtimeMs);
7422            }
7423        }
7424
7425        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
7426            Wakelock wl = mWakelockStats.startObject(name);
7427            if (wl != null) {
7428                wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
7429            }
7430            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
7431                Pid p = getPidStatsLocked(pid);
7432                if (p.mWakeNesting++ == 0) {
7433                    p.mWakeStartMs = elapsedRealtimeMs;
7434                }
7435            }
7436        }
7437
7438        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
7439            Wakelock wl = mWakelockStats.stopObject(name);
7440            if (wl != null) {
7441                wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
7442            }
7443            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
7444                Pid p = mPids.get(pid);
7445                if (p != null && p.mWakeNesting > 0) {
7446                    if (p.mWakeNesting-- == 1) {
7447                        p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
7448                        p.mWakeStartMs = 0;
7449                    }
7450                }
7451            }
7452        }
7453
7454        public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
7455            Proc p = getProcessStatsLocked(proc);
7456            if (p != null) {
7457                p.addExcessiveWake(overTime, usedTime);
7458            }
7459        }
7460
7461        public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
7462            Proc p = getProcessStatsLocked(proc);
7463            if (p != null) {
7464                p.addExcessiveCpu(overTime, usedTime);
7465            }
7466        }
7467
7468        public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
7469            StopwatchTimer t = getSensorTimerLocked(sensor, true);
7470            if (t != null) {
7471                t.startRunningLocked(elapsedRealtimeMs);
7472            }
7473        }
7474
7475        public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
7476            // Don't create a timer if one doesn't already exist
7477            StopwatchTimer t = getSensorTimerLocked(sensor, false);
7478            if (t != null) {
7479                t.stopRunningLocked(elapsedRealtimeMs);
7480            }
7481        }
7482
7483        public void noteStartGps(long elapsedRealtimeMs) {
7484            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
7485            if (t != null) {
7486                t.startRunningLocked(elapsedRealtimeMs);
7487            }
7488        }
7489
7490        public void noteStopGps(long elapsedRealtimeMs) {
7491            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
7492            if (t != null) {
7493                t.stopRunningLocked(elapsedRealtimeMs);
7494            }
7495        }
7496
7497        public BatteryStatsImpl getBatteryStats() {
7498            return mBsi;
7499        }
7500    }
7501
7502    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
7503        this(new SystemClocks(), systemDir, handler, externalSync, null);
7504    }
7505
7506    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync,
7507                            PlatformIdleStateCallback cb) {
7508        this(new SystemClocks(), systemDir, handler, externalSync, cb);
7509    }
7510
7511    public BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
7512            ExternalStatsSync externalSync, PlatformIdleStateCallback cb) {
7513        init(clocks);
7514
7515        if (systemDir != null) {
7516            mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
7517                    new File(systemDir, "batterystats.bin.tmp"));
7518        } else {
7519            mFile = null;
7520        }
7521        mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
7522        mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
7523        mExternalSync = externalSync;
7524        mHandler = new MyHandler(handler.getLooper());
7525        mStartCount++;
7526        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
7527        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
7528            mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
7529                    mOnBatteryTimeBase);
7530        }
7531        mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
7532        mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
7533                mOnBatteryTimeBase);
7534        mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
7535                mOnBatteryTimeBase);
7536        mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
7537        mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
7538        mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
7539        mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
7540        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
7541            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
7542                    mOnBatteryTimeBase);
7543        }
7544        mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
7545                mOnBatteryTimeBase);
7546        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
7547            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
7548                    mOnBatteryTimeBase);
7549        }
7550        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7551            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
7552            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
7553        }
7554        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
7555        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
7556                NUM_BT_TX_LEVELS);
7557        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
7558                ModemActivityInfo.TX_POWER_LEVELS);
7559
7560        mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
7561        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
7562                mOnBatteryTimeBase);
7563        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
7564        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
7565        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
7566        mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
7567        mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
7568        for (int i=0; i<NUM_WIFI_STATES; i++) {
7569            mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
7570                    mOnBatteryTimeBase);
7571        }
7572        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
7573            mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
7574                    mOnBatteryTimeBase);
7575        }
7576        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7577            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
7578                    mOnBatteryTimeBase);
7579        }
7580        mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
7581        mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
7582        mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
7583        mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
7584        mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
7585        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
7586        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
7587        mOnBattery = mOnBatteryInternal = false;
7588        long uptime = mClocks.uptimeMillis() * 1000;
7589        long realtime = mClocks.elapsedRealtime() * 1000;
7590        initTimes(uptime, realtime);
7591        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
7592        mDischargeStartLevel = 0;
7593        mDischargeUnplugLevel = 0;
7594        mDischargePlugLevel = -1;
7595        mDischargeCurrentLevel = 0;
7596        mCurrentBatteryLevel = 0;
7597        initDischarge();
7598        clearHistoryLocked();
7599        updateDailyDeadlineLocked();
7600        mPlatformIdleStateCallback = cb;
7601    }
7602
7603    public BatteryStatsImpl(Parcel p) {
7604        this(new SystemClocks(), p);
7605    }
7606
7607    public BatteryStatsImpl(Clocks clocks, Parcel p) {
7608        init(clocks);
7609        mFile = null;
7610        mCheckinFile = null;
7611        mDailyFile = null;
7612        mHandler = null;
7613        mExternalSync = null;
7614        clearHistoryLocked();
7615        readFromParcel(p);
7616        mPlatformIdleStateCallback = null;
7617    }
7618
7619    public void setPowerProfile(PowerProfile profile) {
7620        synchronized (this) {
7621            mPowerProfile = profile;
7622
7623            // We need to initialize the KernelCpuSpeedReaders to read from
7624            // the first cpu of each core. Once we have the PowerProfile, we have access to this
7625            // information.
7626            final int numClusters = mPowerProfile.getNumCpuClusters();
7627            mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
7628            int firstCpuOfCluster = 0;
7629            for (int i = 0; i < numClusters; i++) {
7630                final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
7631                mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
7632                        numSpeedSteps);
7633                firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
7634            }
7635
7636            if (mEstimatedBatteryCapacity == -1) {
7637                // Initialize the estimated battery capacity to a known preset one.
7638                mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
7639            }
7640        }
7641    }
7642
7643    public void setCallback(BatteryCallback cb) {
7644        mCallback = cb;
7645    }
7646
7647    public void setRadioScanningTimeout(long timeout) {
7648        if (mPhoneSignalScanningTimer != null) {
7649            mPhoneSignalScanningTimer.setTimeout(timeout);
7650        }
7651    }
7652
7653    public void updateDailyDeadlineLocked() {
7654        // Get the current time.
7655        long currentTime = mDailyStartTime = System.currentTimeMillis();
7656        Calendar calDeadline = Calendar.getInstance();
7657        calDeadline.setTimeInMillis(currentTime);
7658
7659        // Move time up to the next day, ranging from 1am to 3pm.
7660        calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
7661        calDeadline.set(Calendar.MILLISECOND, 0);
7662        calDeadline.set(Calendar.SECOND, 0);
7663        calDeadline.set(Calendar.MINUTE, 0);
7664        calDeadline.set(Calendar.HOUR_OF_DAY, 1);
7665        mNextMinDailyDeadline = calDeadline.getTimeInMillis();
7666        calDeadline.set(Calendar.HOUR_OF_DAY, 3);
7667        mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
7668    }
7669
7670    public void recordDailyStatsIfNeededLocked(boolean settled) {
7671        long currentTime = System.currentTimeMillis();
7672        if (currentTime >= mNextMaxDailyDeadline) {
7673            recordDailyStatsLocked();
7674        } else if (settled && currentTime >= mNextMinDailyDeadline) {
7675            recordDailyStatsLocked();
7676        } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
7677            recordDailyStatsLocked();
7678        }
7679    }
7680
7681    public void recordDailyStatsLocked() {
7682        DailyItem item = new DailyItem();
7683        item.mStartTime = mDailyStartTime;
7684        item.mEndTime = System.currentTimeMillis();
7685        boolean hasData = false;
7686        if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
7687            hasData = true;
7688            item.mDischargeSteps = new LevelStepTracker(
7689                    mDailyDischargeStepTracker.mNumStepDurations,
7690                    mDailyDischargeStepTracker.mStepDurations);
7691        }
7692        if (mDailyChargeStepTracker.mNumStepDurations > 0) {
7693            hasData = true;
7694            item.mChargeSteps = new LevelStepTracker(
7695                    mDailyChargeStepTracker.mNumStepDurations,
7696                    mDailyChargeStepTracker.mStepDurations);
7697        }
7698        if (mDailyPackageChanges != null) {
7699            hasData = true;
7700            item.mPackageChanges = mDailyPackageChanges;
7701            mDailyPackageChanges = null;
7702        }
7703        mDailyDischargeStepTracker.init();
7704        mDailyChargeStepTracker.init();
7705        updateDailyDeadlineLocked();
7706
7707        if (hasData) {
7708            mDailyItems.add(item);
7709            while (mDailyItems.size() > MAX_DAILY_ITEMS) {
7710                mDailyItems.remove(0);
7711            }
7712            final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
7713            try {
7714                XmlSerializer out = new FastXmlSerializer();
7715                out.setOutput(memStream, StandardCharsets.UTF_8.name());
7716                writeDailyItemsLocked(out);
7717                BackgroundThread.getHandler().post(new Runnable() {
7718                    @Override
7719                    public void run() {
7720                        synchronized (mCheckinFile) {
7721                            FileOutputStream stream = null;
7722                            try {
7723                                stream = mDailyFile.startWrite();
7724                                memStream.writeTo(stream);
7725                                stream.flush();
7726                                FileUtils.sync(stream);
7727                                stream.close();
7728                                mDailyFile.finishWrite(stream);
7729                            } catch (IOException e) {
7730                                Slog.w("BatteryStats",
7731                                        "Error writing battery daily items", e);
7732                                mDailyFile.failWrite(stream);
7733                            }
7734                        }
7735                    }
7736                });
7737            } catch (IOException e) {
7738            }
7739        }
7740    }
7741
7742    private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
7743        StringBuilder sb = new StringBuilder(64);
7744        out.startDocument(null, true);
7745        out.startTag(null, "daily-items");
7746        for (int i=0; i<mDailyItems.size(); i++) {
7747            final DailyItem dit = mDailyItems.get(i);
7748            out.startTag(null, "item");
7749            out.attribute(null, "start", Long.toString(dit.mStartTime));
7750            out.attribute(null, "end", Long.toString(dit.mEndTime));
7751            writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
7752            writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
7753            if (dit.mPackageChanges != null) {
7754                for (int j=0; j<dit.mPackageChanges.size(); j++) {
7755                    PackageChange pc = dit.mPackageChanges.get(j);
7756                    if (pc.mUpdate) {
7757                        out.startTag(null, "upd");
7758                        out.attribute(null, "pkg", pc.mPackageName);
7759                        out.attribute(null, "ver", Integer.toString(pc.mVersionCode));
7760                        out.endTag(null, "upd");
7761                    } else {
7762                        out.startTag(null, "rem");
7763                        out.attribute(null, "pkg", pc.mPackageName);
7764                        out.endTag(null, "rem");
7765                    }
7766                }
7767            }
7768            out.endTag(null, "item");
7769        }
7770        out.endTag(null, "daily-items");
7771        out.endDocument();
7772    }
7773
7774    private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
7775            StringBuilder tmpBuilder) throws IOException {
7776        if (steps != null) {
7777            out.startTag(null, tag);
7778            out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
7779            for (int i=0; i<steps.mNumStepDurations; i++) {
7780                out.startTag(null, "s");
7781                tmpBuilder.setLength(0);
7782                steps.encodeEntryAt(i, tmpBuilder);
7783                out.attribute(null, "v", tmpBuilder.toString());
7784                out.endTag(null, "s");
7785            }
7786            out.endTag(null, tag);
7787        }
7788    }
7789
7790    public void readDailyStatsLocked() {
7791        Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
7792        mDailyItems.clear();
7793        FileInputStream stream;
7794        try {
7795            stream = mDailyFile.openRead();
7796        } catch (FileNotFoundException e) {
7797            return;
7798        }
7799        try {
7800            XmlPullParser parser = Xml.newPullParser();
7801            parser.setInput(stream, StandardCharsets.UTF_8.name());
7802            readDailyItemsLocked(parser);
7803        } catch (XmlPullParserException e) {
7804        } finally {
7805            try {
7806                stream.close();
7807            } catch (IOException e) {
7808            }
7809        }
7810    }
7811
7812    private void readDailyItemsLocked(XmlPullParser parser) {
7813        try {
7814            int type;
7815            while ((type = parser.next()) != XmlPullParser.START_TAG
7816                    && type != XmlPullParser.END_DOCUMENT) {
7817                ;
7818            }
7819
7820            if (type != XmlPullParser.START_TAG) {
7821                throw new IllegalStateException("no start tag found");
7822            }
7823
7824            int outerDepth = parser.getDepth();
7825            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7826                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7827                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7828                    continue;
7829                }
7830
7831                String tagName = parser.getName();
7832                if (tagName.equals("item")) {
7833                    readDailyItemTagLocked(parser);
7834                } else {
7835                    Slog.w(TAG, "Unknown element under <daily-items>: "
7836                            + parser.getName());
7837                    XmlUtils.skipCurrentTag(parser);
7838                }
7839            }
7840
7841        } catch (IllegalStateException e) {
7842            Slog.w(TAG, "Failed parsing daily " + e);
7843        } catch (NullPointerException e) {
7844            Slog.w(TAG, "Failed parsing daily " + e);
7845        } catch (NumberFormatException e) {
7846            Slog.w(TAG, "Failed parsing daily " + e);
7847        } catch (XmlPullParserException e) {
7848            Slog.w(TAG, "Failed parsing daily " + e);
7849        } catch (IOException e) {
7850            Slog.w(TAG, "Failed parsing daily " + e);
7851        } catch (IndexOutOfBoundsException e) {
7852            Slog.w(TAG, "Failed parsing daily " + e);
7853        }
7854    }
7855
7856    void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
7857            XmlPullParserException, IOException {
7858        DailyItem dit = new DailyItem();
7859        String attr = parser.getAttributeValue(null, "start");
7860        if (attr != null) {
7861            dit.mStartTime = Long.parseLong(attr);
7862        }
7863        attr = parser.getAttributeValue(null, "end");
7864        if (attr != null) {
7865            dit.mEndTime = Long.parseLong(attr);
7866        }
7867        int outerDepth = parser.getDepth();
7868        int type;
7869        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7870                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7871            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7872                continue;
7873            }
7874
7875            String tagName = parser.getName();
7876            if (tagName.equals("dis")) {
7877                readDailyItemTagDetailsLocked(parser, dit, false, "dis");
7878            } else if (tagName.equals("chg")) {
7879                readDailyItemTagDetailsLocked(parser, dit, true, "chg");
7880            } else if (tagName.equals("upd")) {
7881                if (dit.mPackageChanges == null) {
7882                    dit.mPackageChanges = new ArrayList<>();
7883                }
7884                PackageChange pc = new PackageChange();
7885                pc.mUpdate = true;
7886                pc.mPackageName = parser.getAttributeValue(null, "pkg");
7887                String verStr = parser.getAttributeValue(null, "ver");
7888                pc.mVersionCode = verStr != null ? Integer.parseInt(verStr) : 0;
7889                dit.mPackageChanges.add(pc);
7890                XmlUtils.skipCurrentTag(parser);
7891            } else if (tagName.equals("rem")) {
7892                if (dit.mPackageChanges == null) {
7893                    dit.mPackageChanges = new ArrayList<>();
7894                }
7895                PackageChange pc = new PackageChange();
7896                pc.mUpdate = false;
7897                pc.mPackageName = parser.getAttributeValue(null, "pkg");
7898                dit.mPackageChanges.add(pc);
7899                XmlUtils.skipCurrentTag(parser);
7900            } else {
7901                Slog.w(TAG, "Unknown element under <item>: "
7902                        + parser.getName());
7903                XmlUtils.skipCurrentTag(parser);
7904            }
7905        }
7906        mDailyItems.add(dit);
7907    }
7908
7909    void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
7910            String tag)
7911            throws NumberFormatException, XmlPullParserException, IOException {
7912        final String numAttr = parser.getAttributeValue(null, "n");
7913        if (numAttr == null) {
7914            Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
7915            XmlUtils.skipCurrentTag(parser);
7916            return;
7917        }
7918        final int num = Integer.parseInt(numAttr);
7919        LevelStepTracker steps = new LevelStepTracker(num);
7920        if (isCharge) {
7921            dit.mChargeSteps = steps;
7922        } else {
7923            dit.mDischargeSteps = steps;
7924        }
7925        int i = 0;
7926        int outerDepth = parser.getDepth();
7927        int type;
7928        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7929                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7930            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7931                continue;
7932            }
7933
7934            String tagName = parser.getName();
7935            if ("s".equals(tagName)) {
7936                if (i < num) {
7937                    String valueAttr = parser.getAttributeValue(null, "v");
7938                    if (valueAttr != null) {
7939                        steps.decodeEntryAt(i, valueAttr);
7940                        i++;
7941                    }
7942                }
7943            } else {
7944                Slog.w(TAG, "Unknown element under <" + tag + ">: "
7945                        + parser.getName());
7946                XmlUtils.skipCurrentTag(parser);
7947            }
7948        }
7949        steps.mNumStepDurations = i;
7950    }
7951
7952    @Override
7953    public DailyItem getDailyItemLocked(int daysAgo) {
7954        int index = mDailyItems.size()-1-daysAgo;
7955        return index >= 0 ? mDailyItems.get(index) : null;
7956    }
7957
7958    @Override
7959    public long getCurrentDailyStartTime() {
7960        return mDailyStartTime;
7961    }
7962
7963    @Override
7964    public long getNextMinDailyDeadline() {
7965        return mNextMinDailyDeadline;
7966    }
7967
7968    @Override
7969    public long getNextMaxDailyDeadline() {
7970        return mNextMaxDailyDeadline;
7971    }
7972
7973    @Override
7974    public boolean startIteratingOldHistoryLocked() {
7975        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
7976                + " pos=" + mHistoryBuffer.dataPosition());
7977        if ((mHistoryIterator = mHistory) == null) {
7978            return false;
7979        }
7980        mHistoryBuffer.setDataPosition(0);
7981        mHistoryReadTmp.clear();
7982        mReadOverflow = false;
7983        mIteratingHistory = true;
7984        return true;
7985    }
7986
7987    @Override
7988    public boolean getNextOldHistoryLocked(HistoryItem out) {
7989        boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
7990        if (!end) {
7991            readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
7992            mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
7993        }
7994        HistoryItem cur = mHistoryIterator;
7995        if (cur == null) {
7996            if (!mReadOverflow && !end) {
7997                Slog.w(TAG, "Old history ends before new history!");
7998            }
7999            return false;
8000        }
8001        out.setTo(cur);
8002        mHistoryIterator = cur.next;
8003        if (!mReadOverflow) {
8004            if (end) {
8005                Slog.w(TAG, "New history ends before old history!");
8006            } else if (!out.same(mHistoryReadTmp)) {
8007                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
8008                pw.println("Histories differ!");
8009                pw.println("Old history:");
8010                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
8011                pw.println("New history:");
8012                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
8013                        true);
8014                pw.flush();
8015            }
8016        }
8017        return true;
8018    }
8019
8020    @Override
8021    public void finishIteratingOldHistoryLocked() {
8022        mIteratingHistory = false;
8023        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
8024        mHistoryIterator = null;
8025    }
8026
8027    public int getHistoryTotalSize() {
8028        return MAX_HISTORY_BUFFER;
8029    }
8030
8031    public int getHistoryUsedSize() {
8032        return mHistoryBuffer.dataSize();
8033    }
8034
8035    @Override
8036    public boolean startIteratingHistoryLocked() {
8037        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
8038                + " pos=" + mHistoryBuffer.dataPosition());
8039        if (mHistoryBuffer.dataSize() <= 0) {
8040            return false;
8041        }
8042        mHistoryBuffer.setDataPosition(0);
8043        mReadOverflow = false;
8044        mIteratingHistory = true;
8045        mReadHistoryStrings = new String[mHistoryTagPool.size()];
8046        mReadHistoryUids = new int[mHistoryTagPool.size()];
8047        mReadHistoryChars = 0;
8048        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
8049            final HistoryTag tag = ent.getKey();
8050            final int idx = ent.getValue();
8051            mReadHistoryStrings[idx] = tag.string;
8052            mReadHistoryUids[idx] = tag.uid;
8053            mReadHistoryChars += tag.string.length() + 1;
8054        }
8055        return true;
8056    }
8057
8058    @Override
8059    public int getHistoryStringPoolSize() {
8060        return mReadHistoryStrings.length;
8061    }
8062
8063    @Override
8064    public int getHistoryStringPoolBytes() {
8065        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
8066        // Each string character is 2 bytes.
8067        return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
8068    }
8069
8070    @Override
8071    public String getHistoryTagPoolString(int index) {
8072        return mReadHistoryStrings[index];
8073    }
8074
8075    @Override
8076    public int getHistoryTagPoolUid(int index) {
8077        return mReadHistoryUids[index];
8078    }
8079
8080    @Override
8081    public boolean getNextHistoryLocked(HistoryItem out) {
8082        final int pos = mHistoryBuffer.dataPosition();
8083        if (pos == 0) {
8084            out.clear();
8085        }
8086        boolean end = pos >= mHistoryBuffer.dataSize();
8087        if (end) {
8088            return false;
8089        }
8090
8091        final long lastRealtime = out.time;
8092        final long lastWalltime = out.currentTime;
8093        readHistoryDelta(mHistoryBuffer, out);
8094        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
8095                && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
8096            out.currentTime = lastWalltime + (out.time - lastRealtime);
8097        }
8098        return true;
8099    }
8100
8101    @Override
8102    public void finishIteratingHistoryLocked() {
8103        mIteratingHistory = false;
8104        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
8105        mReadHistoryStrings = null;
8106    }
8107
8108    @Override
8109    public long getHistoryBaseTime() {
8110        return mHistoryBaseTime;
8111    }
8112
8113    @Override
8114    public int getStartCount() {
8115        return mStartCount;
8116    }
8117
8118    public boolean isOnBattery() {
8119        return mOnBattery;
8120    }
8121
8122    public boolean isCharging() {
8123        return mCharging;
8124    }
8125
8126    public boolean isScreenOn() {
8127        return mScreenState == Display.STATE_ON;
8128    }
8129
8130    void initTimes(long uptime, long realtime) {
8131        mStartClockTime = System.currentTimeMillis();
8132        mOnBatteryTimeBase.init(uptime, realtime);
8133        mOnBatteryScreenOffTimeBase.init(uptime, realtime);
8134        mRealtime = 0;
8135        mUptime = 0;
8136        mRealtimeStart = realtime;
8137        mUptimeStart = uptime;
8138    }
8139
8140    void initDischarge() {
8141        mLowDischargeAmountSinceCharge = 0;
8142        mHighDischargeAmountSinceCharge = 0;
8143        mDischargeAmountScreenOn = 0;
8144        mDischargeAmountScreenOnSinceCharge = 0;
8145        mDischargeAmountScreenOff = 0;
8146        mDischargeAmountScreenOffSinceCharge = 0;
8147        mDischargeStepTracker.init();
8148        mChargeStepTracker.init();
8149        mDischargeScreenOffCounter.reset(false);
8150        mDischargeCounter.reset(false);
8151    }
8152
8153    public void resetAllStatsCmdLocked() {
8154        resetAllStatsLocked();
8155        final long mSecUptime = mClocks.uptimeMillis();
8156        long uptime = mSecUptime * 1000;
8157        long mSecRealtime = mClocks.elapsedRealtime();
8158        long realtime = mSecRealtime * 1000;
8159        mDischargeStartLevel = mHistoryCur.batteryLevel;
8160        pullPendingStateUpdatesLocked();
8161        addHistoryRecordLocked(mSecRealtime, mSecUptime);
8162        mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
8163                = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
8164        mOnBatteryTimeBase.reset(uptime, realtime);
8165        mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
8166        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
8167            if (mScreenState == Display.STATE_ON) {
8168                mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
8169                mDischargeScreenOffUnplugLevel = 0;
8170            } else {
8171                mDischargeScreenOnUnplugLevel = 0;
8172                mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
8173            }
8174            mDischargeAmountScreenOn = 0;
8175            mDischargeAmountScreenOff = 0;
8176        }
8177        initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
8178    }
8179
8180    private void resetAllStatsLocked() {
8181        final long uptimeMillis = mClocks.uptimeMillis();
8182        final long elapsedRealtimeMillis = mClocks.elapsedRealtime();
8183        mStartCount = 0;
8184        initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);
8185        mScreenOnTimer.reset(false);
8186        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
8187            mScreenBrightnessTimer[i].reset(false);
8188        }
8189
8190        if (mPowerProfile != null) {
8191            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
8192        } else {
8193            mEstimatedBatteryCapacity = -1;
8194        }
8195        mInteractiveTimer.reset(false);
8196        mPowerSaveModeEnabledTimer.reset(false);
8197        mLastIdleTimeStart = elapsedRealtimeMillis;
8198        mLongestLightIdleTime = 0;
8199        mLongestFullIdleTime = 0;
8200        mDeviceIdleModeLightTimer.reset(false);
8201        mDeviceIdleModeFullTimer.reset(false);
8202        mDeviceLightIdlingTimer.reset(false);
8203        mDeviceIdlingTimer.reset(false);
8204        mPhoneOnTimer.reset(false);
8205        mAudioOnTimer.reset(false);
8206        mVideoOnTimer.reset(false);
8207        mFlashlightOnTimer.reset(false);
8208        mCameraOnTimer.reset(false);
8209        mBluetoothScanTimer.reset(false);
8210        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
8211            mPhoneSignalStrengthsTimer[i].reset(false);
8212        }
8213        mPhoneSignalScanningTimer.reset(false);
8214        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
8215            mPhoneDataConnectionsTimer[i].reset(false);
8216        }
8217        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
8218            mNetworkByteActivityCounters[i].reset(false);
8219            mNetworkPacketActivityCounters[i].reset(false);
8220        }
8221        mMobileRadioActiveTimer.reset(false);
8222        mMobileRadioActivePerAppTimer.reset(false);
8223        mMobileRadioActiveAdjustedTime.reset(false);
8224        mMobileRadioActiveUnknownTime.reset(false);
8225        mMobileRadioActiveUnknownCount.reset(false);
8226        mWifiOnTimer.reset(false);
8227        mGlobalWifiRunningTimer.reset(false);
8228        for (int i=0; i<NUM_WIFI_STATES; i++) {
8229            mWifiStateTimer[i].reset(false);
8230        }
8231        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
8232            mWifiSupplStateTimer[i].reset(false);
8233        }
8234        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
8235            mWifiSignalStrengthsTimer[i].reset(false);
8236        }
8237        mWifiActivity.reset(false);
8238        mBluetoothActivity.reset(false);
8239        mModemActivity.reset(false);
8240        mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
8241
8242        for (int i=0; i<mUidStats.size(); i++) {
8243            if (mUidStats.valueAt(i).reset()) {
8244                mUidStats.remove(mUidStats.keyAt(i));
8245                i--;
8246            }
8247        }
8248
8249        if (mKernelWakelockStats.size() > 0) {
8250            for (SamplingTimer timer : mKernelWakelockStats.values()) {
8251                mOnBatteryScreenOffTimeBase.remove(timer);
8252            }
8253            mKernelWakelockStats.clear();
8254        }
8255
8256        if (mWakeupReasonStats.size() > 0) {
8257            for (SamplingTimer timer : mWakeupReasonStats.values()) {
8258                mOnBatteryTimeBase.remove(timer);
8259            }
8260            mWakeupReasonStats.clear();
8261        }
8262
8263        mLastHistoryStepDetails = null;
8264        mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
8265        mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
8266        mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
8267        mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
8268        mLastStepStatUserTime = mCurStepStatUserTime = 0;
8269        mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
8270        mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
8271        mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
8272        mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
8273        mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
8274
8275        initDischarge();
8276
8277        clearHistoryLocked();
8278    }
8279
8280    private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
8281        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
8282            if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
8283                // Not recording process starts/stops.
8284                continue;
8285            }
8286            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
8287            if (active == null) {
8288                continue;
8289            }
8290            for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
8291                SparseIntArray uids = ent.getValue();
8292                for (int j=0; j<uids.size(); j++) {
8293                    addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
8294                            uids.keyAt(j));
8295                }
8296            }
8297        }
8298    }
8299
8300    void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
8301        if (oldScreenOn) {
8302            int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
8303            if (diff > 0) {
8304                mDischargeAmountScreenOn += diff;
8305                mDischargeAmountScreenOnSinceCharge += diff;
8306            }
8307        } else {
8308            int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
8309            if (diff > 0) {
8310                mDischargeAmountScreenOff += diff;
8311                mDischargeAmountScreenOffSinceCharge += diff;
8312            }
8313        }
8314        if (newScreenOn) {
8315            mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
8316            mDischargeScreenOffUnplugLevel = 0;
8317        } else {
8318            mDischargeScreenOnUnplugLevel = 0;
8319            mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
8320        }
8321    }
8322
8323    public void pullPendingStateUpdatesLocked() {
8324        if (mOnBatteryInternal) {
8325            final boolean screenOn = mScreenState == Display.STATE_ON;
8326            updateDischargeScreenLevelsLocked(screenOn, screenOn);
8327        }
8328    }
8329
8330    private String[] mMobileIfaces = EmptyArray.STRING;
8331    private String[] mWifiIfaces = EmptyArray.STRING;
8332
8333    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
8334
8335    private static final int NETWORK_STATS_LAST = 0;
8336    private static final int NETWORK_STATS_NEXT = 1;
8337    private static final int NETWORK_STATS_DELTA = 2;
8338
8339    private NetworkStats[] mMobileNetworkStats;
8340    private NetworkStats[] mWifiNetworkStats;
8341
8342    /**
8343     * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
8344     * as a buffer of NetworkStats objects to cycle through when computing deltas.
8345     */
8346    private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
8347                                                    NetworkStats[] networkStatsBuffer)
8348            throws IOException {
8349        if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
8350                false)) {
8351            return null;
8352        }
8353
8354        final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
8355                ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
8356        networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
8357                networkStatsBuffer[NETWORK_STATS_LAST], null, null,
8358                networkStatsBuffer[NETWORK_STATS_DELTA]);
8359        networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
8360        networkStatsBuffer[NETWORK_STATS_LAST] = stats;
8361        return networkStatsBuffer[NETWORK_STATS_DELTA];
8362    }
8363
8364    /**
8365     * Distribute WiFi energy info and network traffic to apps.
8366     * @param info The energy information from the WiFi controller.
8367     */
8368    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
8369        if (DEBUG_ENERGY) {
8370            Slog.d(TAG, "Updating wifi stats");
8371        }
8372
8373        final long elapsedRealtimeMs = mClocks.elapsedRealtime();
8374        NetworkStats delta = null;
8375        try {
8376            if (!ArrayUtils.isEmpty(mWifiIfaces)) {
8377                delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
8378            }
8379        } catch (IOException e) {
8380            Slog.wtf(TAG, "Failed to get wifi network stats", e);
8381            return;
8382        }
8383
8384        if (!mOnBatteryInternal) {
8385            return;
8386        }
8387
8388        SparseLongArray rxPackets = new SparseLongArray();
8389        SparseLongArray txPackets = new SparseLongArray();
8390        long totalTxPackets = 0;
8391        long totalRxPackets = 0;
8392        if (delta != null) {
8393            final int size = delta.size();
8394            for (int i = 0; i < size; i++) {
8395                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
8396
8397                if (DEBUG_ENERGY) {
8398                    Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
8399                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
8400                            + " txPackets=" + entry.txPackets);
8401                }
8402
8403                if (entry.rxBytes == 0 && entry.txBytes == 0) {
8404                    // Skip the lookup below since there is no work to do.
8405                    continue;
8406                }
8407
8408                final Uid u = getUidStatsLocked(mapUid(entry.uid));
8409                if (entry.rxBytes != 0) {
8410                    u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
8411                            entry.rxPackets);
8412                    mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
8413                            entry.rxBytes);
8414                    mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
8415                            entry.rxPackets);
8416
8417                    rxPackets.put(u.getUid(), entry.rxPackets);
8418
8419                    // Sum the total number of packets so that the Rx Power can
8420                    // be evenly distributed amongst the apps.
8421                    totalRxPackets += entry.rxPackets;
8422                }
8423
8424                if (entry.txBytes != 0) {
8425                    u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
8426                            entry.txPackets);
8427                    mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
8428                            entry.txBytes);
8429                    mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
8430                            entry.txPackets);
8431
8432                    txPackets.put(u.getUid(), entry.txPackets);
8433
8434                    // Sum the total number of packets so that the Tx Power can
8435                    // be evenly distributed amongst the apps.
8436                    totalTxPackets += entry.txPackets;
8437                }
8438            }
8439        }
8440
8441        if (info != null) {
8442            mHasWifiReporting = true;
8443
8444            // Measured in mAms
8445            final long txTimeMs = info.getControllerTxTimeMillis();
8446            final long rxTimeMs = info.getControllerRxTimeMillis();
8447            final long idleTimeMs = info.getControllerIdleTimeMillis();
8448            final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
8449
8450            long leftOverRxTimeMs = rxTimeMs;
8451            long leftOverTxTimeMs = txTimeMs;
8452
8453            if (DEBUG_ENERGY) {
8454                Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
8455                Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
8456                Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
8457                Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
8458                Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
8459            }
8460
8461            long totalWifiLockTimeMs = 0;
8462            long totalScanTimeMs = 0;
8463
8464            // On the first pass, collect some totals so that we can normalize power
8465            // calculations if we need to.
8466            final int uidStatsSize = mUidStats.size();
8467            for (int i = 0; i < uidStatsSize; i++) {
8468                final Uid uid = mUidStats.valueAt(i);
8469
8470                // Sum the total scan power for all apps.
8471                totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
8472                        elapsedRealtimeMs * 1000) / 1000;
8473
8474                // Sum the total time holding wifi lock for all apps.
8475                totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
8476                        elapsedRealtimeMs * 1000) / 1000;
8477            }
8478
8479            if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
8480                Slog.d(TAG, "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
8481                        + rxTimeMs + " ms). Normalizing scan time.");
8482            }
8483            if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
8484                Slog.d(TAG, "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
8485                        + txTimeMs + " ms). Normalizing scan time.");
8486            }
8487
8488            // Actually assign and distribute power usage to apps.
8489            for (int i = 0; i < uidStatsSize; i++) {
8490                final Uid uid = mUidStats.valueAt(i);
8491
8492                long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
8493                        elapsedRealtimeMs * 1000) / 1000;
8494                if (scanTimeSinceMarkMs > 0) {
8495                    // Set the new mark so that next time we get new data since this point.
8496                    uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
8497
8498                    long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
8499                    long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
8500
8501                    // Our total scan time is more than the reported Tx/Rx time.
8502                    // This is possible because the cost of a scan is approximate.
8503                    // Let's normalize the result so that we evenly blame each app
8504                    // scanning.
8505                    //
8506                    // This means that we may have apps that transmitted/received packets not be
8507                    // blamed for this, but this is fine as scans are relatively more expensive.
8508                    if (totalScanTimeMs > rxTimeMs) {
8509                        scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
8510                                totalScanTimeMs;
8511                    }
8512                    if (totalScanTimeMs > txTimeMs) {
8513                        scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
8514                                totalScanTimeMs;
8515                    }
8516
8517                    if (DEBUG_ENERGY) {
8518                        Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
8519                                + scanRxTimeSinceMarkMs + " ms  Tx:"
8520                                + scanTxTimeSinceMarkMs + " ms)");
8521                    }
8522
8523                    ControllerActivityCounterImpl activityCounter =
8524                            uid.getOrCreateWifiControllerActivityLocked();
8525                    activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
8526                    activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
8527                    leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
8528                    leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
8529                }
8530
8531                // Distribute evenly the power consumed while Idle to each app holding a WiFi
8532                // lock.
8533                final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
8534                        elapsedRealtimeMs * 1000) / 1000;
8535                if (wifiLockTimeSinceMarkMs > 0) {
8536                    // Set the new mark so that next time we get new data since this point.
8537                    uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
8538
8539                    final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
8540                            / totalWifiLockTimeMs;
8541                    if (DEBUG_ENERGY) {
8542                        Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
8543                                + myIdleTimeMs + " ms");
8544                    }
8545                    uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
8546                            .addCountLocked(myIdleTimeMs);
8547                }
8548            }
8549
8550            if (DEBUG_ENERGY) {
8551                Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
8552                Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
8553            }
8554
8555            // Distribute the remaining Tx power appropriately between all apps that transmitted
8556            // packets.
8557            for (int i = 0; i < txPackets.size(); i++) {
8558                final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
8559                final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets;
8560                if (DEBUG_ENERGY) {
8561                    Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
8562                }
8563                uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
8564                        .addCountLocked(myTxTimeMs);
8565            }
8566
8567            // Distribute the remaining Rx power appropriately between all apps that received
8568            // packets.
8569            for (int i = 0; i < rxPackets.size(); i++) {
8570                final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
8571                final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
8572                if (DEBUG_ENERGY) {
8573                    Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
8574                }
8575                uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
8576                        .addCountLocked(myRxTimeMs);
8577            }
8578
8579            // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
8580
8581            // Update WiFi controller stats.
8582            mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
8583            mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis());
8584            mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis());
8585
8586            // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
8587            final double opVolt = mPowerProfile.getAveragePower(
8588                    PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
8589            if (opVolt != 0) {
8590                // We store the power drain as mAms.
8591                mWifiActivity.getPowerCounter().addCountLocked(
8592                        (long)(info.getControllerEnergyUsed() / opVolt));
8593            }
8594        }
8595    }
8596
8597    /**
8598     * Distribute Cell radio energy info and network traffic to apps.
8599     */
8600    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs,
8601                                             final ModemActivityInfo activityInfo) {
8602        if (DEBUG_ENERGY) {
8603            Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
8604        }
8605
8606        NetworkStats delta = null;
8607        try {
8608            if (!ArrayUtils.isEmpty(mMobileIfaces)) {
8609                delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
8610            }
8611        } catch (IOException e) {
8612            Slog.wtf(TAG, "Failed to get mobile network stats", e);
8613            return;
8614        }
8615
8616        if (!mOnBatteryInternal) {
8617            return;
8618        }
8619
8620        long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
8621                elapsedRealtimeMs * 1000);
8622        mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
8623
8624        long totalRxPackets = 0;
8625        long totalTxPackets = 0;
8626        if (delta != null) {
8627            final int size = delta.size();
8628            for (int i = 0; i < size; i++) {
8629                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
8630                if (entry.rxPackets == 0 && entry.txPackets == 0) {
8631                    continue;
8632                }
8633
8634                if (DEBUG_ENERGY) {
8635                    Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
8636                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
8637                            + " txPackets=" + entry.txPackets);
8638                }
8639
8640                totalRxPackets += entry.rxPackets;
8641                totalTxPackets += entry.txPackets;
8642
8643                final Uid u = getUidStatsLocked(mapUid(entry.uid));
8644                u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
8645                u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
8646
8647                mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
8648                        entry.rxBytes);
8649                mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
8650                        entry.txBytes);
8651                mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
8652                        entry.rxPackets);
8653                mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
8654                        entry.txPackets);
8655            }
8656
8657            // Now distribute proportional blame to the apps that did networking.
8658            long totalPackets = totalRxPackets + totalTxPackets;
8659            if (totalPackets > 0) {
8660                for (int i = 0; i < size; i++) {
8661                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
8662                    if (entry.rxPackets == 0 && entry.txPackets == 0) {
8663                        continue;
8664                    }
8665
8666                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
8667
8668                    // Distribute total radio active time in to this app.
8669                    final long appPackets = entry.rxPackets + entry.txPackets;
8670                    final long appRadioTime = (radioTime * appPackets) / totalPackets;
8671                    u.noteMobileRadioActiveTimeLocked(appRadioTime);
8672
8673                    // Remove this app from the totals, so that we don't lose any time
8674                    // due to rounding.
8675                    radioTime -= appRadioTime;
8676                    totalPackets -= appPackets;
8677
8678                    if (activityInfo != null) {
8679                        ControllerActivityCounterImpl activityCounter =
8680                                u.getOrCreateModemControllerActivityLocked();
8681                        if (totalRxPackets > 0 && entry.rxPackets > 0) {
8682                            final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
8683                                    / totalRxPackets;
8684                            activityCounter.getRxTimeCounter().addCountLocked(rxMs);
8685                        }
8686
8687                        if (totalTxPackets > 0 && entry.txPackets > 0) {
8688                            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
8689                                long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
8690                                txMs /= totalTxPackets;
8691                                activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
8692                            }
8693                        }
8694                    }
8695                }
8696            }
8697
8698            if (radioTime > 0) {
8699                // Whoops, there is some radio time we can't blame on an app!
8700                mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
8701                mMobileRadioActiveUnknownCount.addCountLocked(1);
8702            }
8703        }
8704
8705        if (activityInfo != null) {
8706            mHasModemReporting = true;
8707            mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis());
8708            mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
8709            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
8710                mModemActivity.getTxTimeCounters()[lvl]
8711                        .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
8712            }
8713
8714            // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
8715            final double opVolt = mPowerProfile.getAveragePower(
8716                    PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
8717            if (opVolt != 0) {
8718                // We store the power drain as mAms.
8719                mModemActivity.getPowerCounter().addCountLocked(
8720                        (long) (activityInfo.getEnergyUsed() / opVolt));
8721            }
8722        }
8723    }
8724
8725    /**
8726     * Distribute Bluetooth energy info and network traffic to apps.
8727     * @param info The energy information from the bluetooth controller.
8728     */
8729    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
8730        if (DEBUG_ENERGY) {
8731            Slog.d(TAG, "Updating bluetooth stats: " + info);
8732        }
8733
8734        if (info == null || !mOnBatteryInternal) {
8735            return;
8736        }
8737
8738        mHasBluetoothReporting = true;
8739
8740        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
8741        final long rxTimeMs = info.getControllerRxTimeMillis();
8742        final long txTimeMs = info.getControllerTxTimeMillis();
8743
8744        if (DEBUG_ENERGY) {
8745            Slog.d(TAG, "------ BEGIN BLE power blaming ------");
8746            Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
8747            Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
8748            Slog.d(TAG, "  Idle Time:  " + info.getControllerIdleTimeMillis() + " ms");
8749        }
8750
8751        long totalScanTimeMs = 0;
8752
8753        final int uidCount = mUidStats.size();
8754        for (int i = 0; i < uidCount; i++) {
8755            final Uid u = mUidStats.valueAt(i);
8756            if (u.mBluetoothScanTimer == null) {
8757                continue;
8758            }
8759
8760            totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
8761                    elapsedRealtimeMs * 1000) / 1000;
8762        }
8763
8764        final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
8765        final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
8766
8767        if (DEBUG_ENERGY) {
8768            Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
8769                    + " TX=" + normalizeScanTxTime);
8770        }
8771
8772        long leftOverRxTimeMs = rxTimeMs;
8773        long leftOverTxTimeMs = txTimeMs;
8774
8775        for (int i = 0; i < uidCount; i++) {
8776            final Uid u = mUidStats.valueAt(i);
8777            if (u.mBluetoothScanTimer == null) {
8778                continue;
8779            }
8780
8781            long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
8782                    elapsedRealtimeMs * 1000) / 1000;
8783            if (scanTimeSinceMarkMs > 0) {
8784                // Set the new mark so that next time we get new data since this point.
8785                u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
8786
8787                long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
8788                long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
8789
8790                if (normalizeScanRxTime) {
8791                    // Scan time is longer than the total rx time in the controller,
8792                    // so distribute the scan time proportionately. This means regular traffic
8793                    // will not blamed, but scans are more expensive anyways.
8794                    scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
8795                }
8796
8797                if (normalizeScanTxTime) {
8798                    // Scan time is longer than the total tx time in the controller,
8799                    // so distribute the scan time proportionately. This means regular traffic
8800                    // will not blamed, but scans are more expensive anyways.
8801                    scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
8802                }
8803
8804                final ControllerActivityCounterImpl counter =
8805                        u.getOrCreateBluetoothControllerActivityLocked();
8806                counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
8807                counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
8808
8809                leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
8810                leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
8811            }
8812        }
8813
8814        if (DEBUG_ENERGY) {
8815            Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs
8816                    + " TX=" + leftOverTxTimeMs);
8817        }
8818
8819        //
8820        // Now distribute blame to apps that did bluetooth traffic.
8821        //
8822
8823        long totalTxBytes = 0;
8824        long totalRxBytes = 0;
8825
8826        final UidTraffic[] uidTraffic = info.getUidTraffic();
8827        final int numUids = uidTraffic != null ? uidTraffic.length : 0;
8828        for (int i = 0; i < numUids; i++) {
8829            final UidTraffic traffic = uidTraffic[i];
8830
8831            // Add to the global counters.
8832            mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
8833                    traffic.getRxBytes());
8834            mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(
8835                    traffic.getTxBytes());
8836
8837            // Add to the UID counters.
8838            final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
8839            u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0);
8840            u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0);
8841
8842            // Calculate the total traffic.
8843            totalTxBytes += traffic.getTxBytes();
8844            totalRxBytes += traffic.getRxBytes();
8845        }
8846
8847        if ((totalTxBytes != 0 || totalRxBytes != 0) &&
8848                (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) {
8849            for (int i = 0; i < numUids; i++) {
8850                final UidTraffic traffic = uidTraffic[i];
8851
8852                final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
8853                final ControllerActivityCounterImpl counter =
8854                        u.getOrCreateBluetoothControllerActivityLocked();
8855
8856                if (totalRxBytes > 0 && traffic.getRxBytes() > 0) {
8857                    final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes;
8858
8859                    if (DEBUG_ENERGY) {
8860                        Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes()
8861                                + " rx_time=" + timeRxMs);
8862                    }
8863                    counter.getRxTimeCounter().addCountLocked(timeRxMs);
8864                    leftOverRxTimeMs -= timeRxMs;
8865                }
8866
8867                if (totalTxBytes > 0 && traffic.getTxBytes() > 0) {
8868                    final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes;
8869
8870                    if (DEBUG_ENERGY) {
8871                        Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes()
8872                                + " tx_time=" + timeTxMs);
8873                    }
8874
8875                    counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
8876                    leftOverTxTimeMs -= timeTxMs;
8877                }
8878            }
8879        }
8880
8881        mBluetoothActivity.getRxTimeCounter().addCountLocked(
8882                info.getControllerRxTimeMillis());
8883        mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
8884                info.getControllerTxTimeMillis());
8885        mBluetoothActivity.getIdleTimeCounter().addCountLocked(
8886                info.getControllerIdleTimeMillis());
8887
8888        // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
8889        final double opVolt = mPowerProfile.getAveragePower(
8890                PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
8891        if (opVolt != 0) {
8892            // We store the power drain as mAms.
8893            mBluetoothActivity.getPowerCounter().addCountLocked(
8894                    (long) (info.getControllerEnergyUsed() / opVolt));
8895        }
8896    }
8897
8898    /**
8899     * Read and distribute kernel wake lock use across apps.
8900     */
8901    public void updateKernelWakelocksLocked() {
8902        final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
8903                mTmpWakelockStats);
8904        if (wakelockStats == null) {
8905            // Not crashing might make board bringup easier.
8906            Slog.w(TAG, "Couldn't get kernel wake lock stats");
8907            return;
8908        }
8909
8910        for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
8911            String name = ent.getKey();
8912            KernelWakelockStats.Entry kws = ent.getValue();
8913
8914            SamplingTimer kwlt = mKernelWakelockStats.get(name);
8915            if (kwlt == null) {
8916                kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
8917                mKernelWakelockStats.put(name, kwlt);
8918            }
8919
8920            kwlt.update(kws.mTotalTime, kws.mCount);
8921            kwlt.setUpdateVersion(kws.mVersion);
8922        }
8923
8924        int numWakelocksSetStale = 0;
8925        // Set timers to stale if they didn't appear in /d/wakeup_sources (or /proc/wakelocks)
8926        // this time.
8927        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
8928            SamplingTimer st = ent.getValue();
8929            if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
8930                st.endSample();
8931                numWakelocksSetStale++;
8932            }
8933        }
8934
8935        // Record whether we've seen a non-zero time (for debugging b/22716723).
8936        if (wakelockStats.isEmpty()) {
8937            Slog.wtf(TAG, "All kernel wakelocks had time of zero");
8938        }
8939
8940        if (numWakelocksSetStale == mKernelWakelockStats.size()) {
8941            Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
8942                    wakelockStats.kernelWakelockVersion);
8943        }
8944    }
8945
8946    // We use an anonymous class to access these variables,
8947    // so they can't live on the stack or they'd have to be
8948    // final MutableLong objects (more allocations).
8949    // Used in updateCpuTimeLocked().
8950    long mTempTotalCpuUserTimeUs;
8951    long mTempTotalCpuSystemTimeUs;
8952
8953    /**
8954     * Read and distribute CPU usage across apps. If their are partial wakelocks being held
8955     * and we are on battery with screen off, we give more of the cpu time to those apps holding
8956     * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
8957     */
8958    public void updateCpuTimeLocked() {
8959        if (mPowerProfile == null) {
8960            return;
8961        }
8962
8963        if (DEBUG_ENERGY_CPU) {
8964            Slog.d(TAG, "!Cpu updating!");
8965        }
8966
8967        // Holding a wakelock costs more than just using the cpu.
8968        // Currently, we assign only half the cpu time to an app that is running but
8969        // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
8970        // If no app is holding a wakelock, then the distribution is normal.
8971        final int wakelockWeight = 50;
8972
8973        // Read the time spent for each cluster at various cpu frequencies.
8974        final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
8975        for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
8976            clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
8977        }
8978
8979        int numWakelocks = 0;
8980
8981        // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
8982        // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
8983        final int numPartialTimers = mPartialTimers.size();
8984        if (mOnBatteryScreenOffTimeBase.isRunning()) {
8985            for (int i = 0; i < numPartialTimers; i++) {
8986                final StopwatchTimer timer = mPartialTimers.get(i);
8987                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
8988                    // Since the collection and blaming of wakelocks can be scheduled to run after
8989                    // some delay, the mPartialTimers list may have new entries. We can't blame
8990                    // the newly added timer for past cpu time, so we only consider timers that
8991                    // were present for one round of collection. Once a timer has gone through
8992                    // a round of collection, its mInList field is set to true.
8993                    numWakelocks++;
8994                }
8995            }
8996        }
8997
8998        final int numWakelocksF = numWakelocks;
8999        mTempTotalCpuUserTimeUs = 0;
9000        mTempTotalCpuSystemTimeUs = 0;
9001
9002        // Read the CPU data for each UID. This will internally generate a snapshot so next time
9003        // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
9004        // we just ignore the data.
9005        final long startTimeMs = mClocks.elapsedRealtime();
9006        mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
9007                new KernelUidCpuTimeReader.Callback() {
9008                    @Override
9009                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
9010                                             long powerMaUs) {
9011                        final Uid u = getUidStatsLocked(mapUid(uid));
9012
9013                        // Accumulate the total system and user time.
9014                        mTempTotalCpuUserTimeUs += userTimeUs;
9015                        mTempTotalCpuSystemTimeUs += systemTimeUs;
9016
9017                        StringBuilder sb = null;
9018                        if (DEBUG_ENERGY_CPU) {
9019                            sb = new StringBuilder();
9020                            sb.append("  got time for uid=").append(u.mUid).append(": u=");
9021                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
9022                            sb.append(" s=");
9023                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
9024                            sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
9025                        }
9026
9027                        if (numWakelocksF > 0) {
9028                            // We have wakelocks being held, so only give a portion of the
9029                            // time to the process. The rest will be distributed among wakelock
9030                            // holders.
9031                            userTimeUs = (userTimeUs * wakelockWeight) / 100;
9032                            systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
9033                        }
9034
9035                        if (sb != null) {
9036                            sb.append("  adding to uid=").append(u.mUid).append(": u=");
9037                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
9038                            sb.append(" s=");
9039                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
9040                            sb.append(" p=").append(powerMaUs / 1000).append("mAms");
9041                            Slog.d(TAG, sb.toString());
9042                        }
9043
9044                        u.mUserCpuTime.addCountLocked(userTimeUs);
9045                        u.mSystemCpuTime.addCountLocked(systemTimeUs);
9046                        u.mCpuPower.addCountLocked(powerMaUs);
9047
9048                        // Add the cpu speeds to this UID. These are used as a ratio
9049                        // for computing the power this UID used.
9050                        final int numClusters = mPowerProfile.getNumCpuClusters();
9051                        if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
9052                                numClusters) {
9053                            u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
9054                        }
9055
9056                        for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
9057                            final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(
9058                                    cluster);
9059                            if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
9060                                    u.mCpuClusterSpeed[cluster].length) {
9061                                u.mCpuClusterSpeed[cluster] =
9062                                        new LongSamplingCounter[speedsInCluster];
9063                            }
9064
9065                            final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
9066                            for (int speed = 0; speed < clusterSpeeds[cluster].length; speed++) {
9067                                if (cpuSpeeds[speed] == null) {
9068                                    cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
9069                                }
9070                                cpuSpeeds[speed].addCountLocked(clusterSpeeds[cluster][speed]);
9071                            }
9072                        }
9073                    }
9074                });
9075
9076        if (DEBUG_ENERGY_CPU) {
9077            Slog.d(TAG, "Reading cpu stats took " + (mClocks.elapsedRealtime() - startTimeMs) +
9078                    " ms");
9079        }
9080
9081        if (mOnBatteryInternal && numWakelocks > 0) {
9082            // Distribute a portion of the total cpu time to wakelock holders.
9083            mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
9084            mTempTotalCpuSystemTimeUs =
9085                    (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
9086
9087            for (int i = 0; i < numPartialTimers; i++) {
9088                final StopwatchTimer timer = mPartialTimers.get(i);
9089
9090                // The system does not share any blame, as it is usually holding the wakelock
9091                // on behalf of an app.
9092                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
9093                    int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
9094                    int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
9095
9096                    if (DEBUG_ENERGY_CPU) {
9097                        StringBuilder sb = new StringBuilder();
9098                        sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
9099                                .append(": u=");
9100                        TimeUtils.formatDuration(userTimeUs / 1000, sb);
9101                        sb.append(" s=");
9102                        TimeUtils.formatDuration(systemTimeUs / 1000, sb);
9103                        Slog.d(TAG, sb.toString());
9104                    }
9105
9106                    timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
9107                    timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
9108
9109                    final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
9110                    proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
9111
9112                    mTempTotalCpuUserTimeUs -= userTimeUs;
9113                    mTempTotalCpuSystemTimeUs -= systemTimeUs;
9114                    numWakelocks--;
9115                }
9116            }
9117
9118            if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
9119                // Anything left over is given to the system.
9120                if (DEBUG_ENERGY_CPU) {
9121                    StringBuilder sb = new StringBuilder();
9122                    sb.append("  Distributing lost time to system: u=");
9123                    TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
9124                    sb.append(" s=");
9125                    TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
9126                    Slog.d(TAG, sb.toString());
9127                }
9128
9129                final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
9130                u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
9131                u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
9132
9133                final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
9134                proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000,
9135                        (int) mTempTotalCpuSystemTimeUs / 1000);
9136            }
9137        }
9138
9139        // See if there is a difference in wakelocks between this collection and the last
9140        // collection.
9141        if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
9142            // No difference, so each timer is now considered for the next collection.
9143            for (int i = 0; i < numPartialTimers; i++) {
9144                mPartialTimers.get(i).mInList = true;
9145            }
9146        } else {
9147            // The lists are different, meaning we added (or removed a timer) since the last
9148            // collection.
9149            final int numLastPartialTimers = mLastPartialTimers.size();
9150            for (int i = 0; i < numLastPartialTimers; i++) {
9151                mLastPartialTimers.get(i).mInList = false;
9152            }
9153            mLastPartialTimers.clear();
9154
9155            // Mark the current timers as gone through a collection.
9156            for (int i = 0; i < numPartialTimers; i++) {
9157                final StopwatchTimer timer = mPartialTimers.get(i);
9158                timer.mInList = true;
9159                mLastPartialTimers.add(timer);
9160            }
9161        }
9162    }
9163
9164    boolean setChargingLocked(boolean charging) {
9165        if (mCharging != charging) {
9166            mCharging = charging;
9167            if (charging) {
9168                mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
9169            } else {
9170                mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
9171            }
9172            mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
9173            return true;
9174        }
9175        return false;
9176    }
9177
9178    void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
9179            final int oldStatus, final int level, final int chargeUAh) {
9180        boolean doWrite = false;
9181        Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
9182        m.arg1 = onBattery ? 1 : 0;
9183        mHandler.sendMessage(m);
9184
9185        final long uptime = mSecUptime * 1000;
9186        final long realtime = mSecRealtime * 1000;
9187        final boolean screenOn = mScreenState == Display.STATE_ON;
9188        if (onBattery) {
9189            // We will reset our status if we are unplugging after the
9190            // battery was last full, or the level is at 100, or
9191            // we have gone through a significant charge (from a very low
9192            // level to a now very high level).
9193            boolean reset = false;
9194            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
9195                    || level >= 90
9196                    || (mDischargeCurrentLevel < 20 && level >= 80)
9197                    || (getHighDischargeAmountSinceCharge() >= 200
9198                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
9199                Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
9200                        + " dischargeLevel=" + mDischargeCurrentLevel
9201                        + " lowAmount=" + getLowDischargeAmountSinceCharge()
9202                        + " highAmount=" + getHighDischargeAmountSinceCharge());
9203                // Before we write, collect a snapshot of the final aggregated
9204                // stats to be reported in the next checkin.  Only do this if we have
9205                // a sufficient amount of data to make it interesting.
9206                if (getLowDischargeAmountSinceCharge() >= 20) {
9207                    final Parcel parcel = Parcel.obtain();
9208                    writeSummaryToParcel(parcel, true);
9209                    BackgroundThread.getHandler().post(new Runnable() {
9210                        @Override public void run() {
9211                            synchronized (mCheckinFile) {
9212                                FileOutputStream stream = null;
9213                                try {
9214                                    stream = mCheckinFile.startWrite();
9215                                    stream.write(parcel.marshall());
9216                                    stream.flush();
9217                                    FileUtils.sync(stream);
9218                                    stream.close();
9219                                    mCheckinFile.finishWrite(stream);
9220                                } catch (IOException e) {
9221                                    Slog.w("BatteryStats",
9222                                            "Error writing checkin battery statistics", e);
9223                                    mCheckinFile.failWrite(stream);
9224                                } finally {
9225                                    parcel.recycle();
9226                                }
9227                            }
9228                        }
9229                    });
9230                }
9231                doWrite = true;
9232                resetAllStatsLocked();
9233                if (chargeUAh > 0) {
9234                    // Only use the reported coulomb charge value if it is supported and reported.
9235                    mEstimatedBatteryCapacity = (int) ((level / 100.0) * (chargeUAh / 1000));
9236                }
9237                mDischargeStartLevel = level;
9238                reset = true;
9239                mDischargeStepTracker.init();
9240            }
9241            if (mCharging) {
9242                setChargingLocked(false);
9243            }
9244            mLastChargingStateLevel = level;
9245            mOnBattery = mOnBatteryInternal = true;
9246            mLastDischargeStepLevel = level;
9247            mMinDischargeStepLevel = level;
9248            mDischargeStepTracker.clearTime();
9249            mDailyDischargeStepTracker.clearTime();
9250            mInitStepMode = mCurStepMode;
9251            mModStepMode = 0;
9252            pullPendingStateUpdatesLocked();
9253            mHistoryCur.batteryLevel = (byte)level;
9254            mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
9255            if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
9256                    + Integer.toHexString(mHistoryCur.states));
9257            if (reset) {
9258                mRecordingHistory = true;
9259                startRecordingHistory(mSecRealtime, mSecUptime, reset);
9260            }
9261            addHistoryRecordLocked(mSecRealtime, mSecUptime);
9262            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
9263            if (screenOn) {
9264                mDischargeScreenOnUnplugLevel = level;
9265                mDischargeScreenOffUnplugLevel = 0;
9266            } else {
9267                mDischargeScreenOnUnplugLevel = 0;
9268                mDischargeScreenOffUnplugLevel = level;
9269            }
9270            mDischargeAmountScreenOn = 0;
9271            mDischargeAmountScreenOff = 0;
9272            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
9273        } else {
9274            mLastChargingStateLevel = level;
9275            mOnBattery = mOnBatteryInternal = false;
9276            pullPendingStateUpdatesLocked();
9277            mHistoryCur.batteryLevel = (byte)level;
9278            mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
9279            if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
9280                    + Integer.toHexString(mHistoryCur.states));
9281            addHistoryRecordLocked(mSecRealtime, mSecUptime);
9282            mDischargeCurrentLevel = mDischargePlugLevel = level;
9283            if (level < mDischargeUnplugLevel) {
9284                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
9285                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
9286            }
9287            updateDischargeScreenLevelsLocked(screenOn, screenOn);
9288            updateTimeBasesLocked(false, !screenOn, uptime, realtime);
9289            mChargeStepTracker.init();
9290            mLastChargeStepLevel = level;
9291            mMaxChargeStepLevel = level;
9292            mInitStepMode = mCurStepMode;
9293            mModStepMode = 0;
9294        }
9295        if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
9296            if (mFile != null) {
9297                writeAsyncLocked();
9298            }
9299        }
9300    }
9301
9302    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
9303            boolean reset) {
9304        mRecordingHistory = true;
9305        mHistoryCur.currentTime = System.currentTimeMillis();
9306        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
9307                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
9308                mHistoryCur);
9309        mHistoryCur.currentTime = 0;
9310        if (reset) {
9311            initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
9312        }
9313    }
9314
9315    private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
9316            final long uptimeMs) {
9317        if (mRecordingHistory) {
9318            mHistoryCur.currentTime = currentTime;
9319            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
9320                    mHistoryCur);
9321            mHistoryCur.currentTime = 0;
9322        }
9323    }
9324
9325    private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
9326        if (mRecordingHistory) {
9327            mHistoryCur.currentTime = System.currentTimeMillis();
9328            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
9329                    mHistoryCur);
9330            mHistoryCur.currentTime = 0;
9331        }
9332    }
9333
9334    private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
9335        if (mExternalSync != null) {
9336            mExternalSync.scheduleSync(reason, updateFlags);
9337        }
9338    }
9339
9340    // This should probably be exposed in the API, though it's not critical
9341    public static final int BATTERY_PLUGGED_NONE = 0;
9342
9343    public void setBatteryStateLocked(int status, int health, int plugType, int level,
9344            int temp, int volt, int chargeUAh) {
9345        final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
9346        final long uptime = mClocks.uptimeMillis();
9347        final long elapsedRealtime = mClocks.elapsedRealtime();
9348        if (!mHaveBatteryLevel) {
9349            mHaveBatteryLevel = true;
9350            // We start out assuming that the device is plugged in (not
9351            // on battery).  If our first report is now that we are indeed
9352            // plugged in, then twiddle our state to correctly reflect that
9353            // since we won't be going through the full setOnBattery().
9354            if (onBattery == mOnBattery) {
9355                if (onBattery) {
9356                    mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
9357                } else {
9358                    mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
9359                }
9360            }
9361            // Always start out assuming charging, that will be updated later.
9362            mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
9363            mHistoryCur.batteryStatus = (byte)status;
9364            mHistoryCur.batteryLevel = (byte)level;
9365            mHistoryCur.batteryChargeUAh = chargeUAh;
9366            mMaxChargeStepLevel = mMinDischargeStepLevel =
9367                    mLastChargeStepLevel = mLastDischargeStepLevel = level;
9368            mLastChargingStateLevel = level;
9369        } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
9370            recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
9371        }
9372        int oldStatus = mHistoryCur.batteryStatus;
9373        if (onBattery) {
9374            mDischargeCurrentLevel = level;
9375            if (!mRecordingHistory) {
9376                mRecordingHistory = true;
9377                startRecordingHistory(elapsedRealtime, uptime, true);
9378            }
9379        } else if (level < 96) {
9380            if (!mRecordingHistory) {
9381                mRecordingHistory = true;
9382                startRecordingHistory(elapsedRealtime, uptime, true);
9383            }
9384        }
9385        mCurrentBatteryLevel = level;
9386        if (mDischargePlugLevel < 0) {
9387            mDischargePlugLevel = level;
9388        }
9389
9390        if (onBattery != mOnBattery) {
9391            mHistoryCur.batteryLevel = (byte)level;
9392            mHistoryCur.batteryStatus = (byte)status;
9393            mHistoryCur.batteryHealth = (byte)health;
9394            mHistoryCur.batteryPlugType = (byte)plugType;
9395            mHistoryCur.batteryTemperature = (short)temp;
9396            mHistoryCur.batteryVoltage = (char)volt;
9397            if (chargeUAh < mHistoryCur.batteryChargeUAh) {
9398                // Only record discharges
9399                final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
9400                mDischargeCounter.addCountLocked(chargeDiff);
9401                mDischargeScreenOffCounter.addCountLocked(chargeDiff);
9402            }
9403            mHistoryCur.batteryChargeUAh = chargeUAh;
9404            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
9405        } else {
9406            boolean changed = false;
9407            if (mHistoryCur.batteryLevel != level) {
9408                mHistoryCur.batteryLevel = (byte)level;
9409                changed = true;
9410
9411                // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
9412                // which will pull external stats.
9413                scheduleSyncExternalStatsLocked("battery-level", ExternalStatsSync.UPDATE_ALL);
9414            }
9415            if (mHistoryCur.batteryStatus != status) {
9416                mHistoryCur.batteryStatus = (byte)status;
9417                changed = true;
9418            }
9419            if (mHistoryCur.batteryHealth != health) {
9420                mHistoryCur.batteryHealth = (byte)health;
9421                changed = true;
9422            }
9423            if (mHistoryCur.batteryPlugType != plugType) {
9424                mHistoryCur.batteryPlugType = (byte)plugType;
9425                changed = true;
9426            }
9427            if (temp >= (mHistoryCur.batteryTemperature+10)
9428                    || temp <= (mHistoryCur.batteryTemperature-10)) {
9429                mHistoryCur.batteryTemperature = (short)temp;
9430                changed = true;
9431            }
9432            if (volt > (mHistoryCur.batteryVoltage+20)
9433                    || volt < (mHistoryCur.batteryVoltage-20)) {
9434                mHistoryCur.batteryVoltage = (char)volt;
9435                changed = true;
9436            }
9437            if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
9438                    || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
9439                if (chargeUAh < mHistoryCur.batteryChargeUAh) {
9440                    // Only record discharges
9441                    final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
9442                    mDischargeCounter.addCountLocked(chargeDiff);
9443                    mDischargeScreenOffCounter.addCountLocked(chargeDiff);
9444                }
9445                mHistoryCur.batteryChargeUAh = chargeUAh;
9446                changed = true;
9447            }
9448            long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
9449                    | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
9450                    | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
9451            if (onBattery) {
9452                changed |= setChargingLocked(false);
9453                if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
9454                    mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
9455                            modeBits, elapsedRealtime);
9456                    mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
9457                            modeBits, elapsedRealtime);
9458                    mLastDischargeStepLevel = level;
9459                    mMinDischargeStepLevel = level;
9460                    mInitStepMode = mCurStepMode;
9461                    mModStepMode = 0;
9462                }
9463            } else {
9464                if (level >= 90) {
9465                    // If the battery level is at least 90%, always consider the device to be
9466                    // charging even if it happens to go down a level.
9467                    changed |= setChargingLocked(true);
9468                    mLastChargeStepLevel = level;
9469                } if (!mCharging) {
9470                    if (mLastChargeStepLevel < level) {
9471                        // We have not reporting that we are charging, but the level has now
9472                        // gone up, so consider the state to be charging.
9473                        changed |= setChargingLocked(true);
9474                        mLastChargeStepLevel = level;
9475                    }
9476                } else {
9477                    if (mLastChargeStepLevel > level) {
9478                        // We had reported that the device was charging, but here we are with
9479                        // power connected and the level going down.  Looks like the current
9480                        // power supplied isn't enough, so consider the device to now be
9481                        // discharging.
9482                        changed |= setChargingLocked(false);
9483                        mLastChargeStepLevel = level;
9484                    }
9485                }
9486                if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
9487                    mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
9488                            modeBits, elapsedRealtime);
9489                    mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
9490                            modeBits, elapsedRealtime);
9491                    mLastChargeStepLevel = level;
9492                    mMaxChargeStepLevel = level;
9493                    mInitStepMode = mCurStepMode;
9494                    mModStepMode = 0;
9495                }
9496            }
9497            if (changed) {
9498                addHistoryRecordLocked(elapsedRealtime, uptime);
9499            }
9500        }
9501        if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
9502            // We don't record history while we are plugged in and fully charged.
9503            // The next time we are unplugged, history will be cleared.
9504            mRecordingHistory = DEBUG;
9505        }
9506    }
9507
9508    public long getAwakeTimeBattery() {
9509        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
9510    }
9511
9512    public long getAwakeTimePlugged() {
9513        return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
9514    }
9515
9516    @Override
9517    public long computeUptime(long curTime, int which) {
9518        switch (which) {
9519            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
9520            case STATS_CURRENT: return (curTime-mUptimeStart);
9521            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
9522        }
9523        return 0;
9524    }
9525
9526    @Override
9527    public long computeRealtime(long curTime, int which) {
9528        switch (which) {
9529            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
9530            case STATS_CURRENT: return (curTime-mRealtimeStart);
9531            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
9532        }
9533        return 0;
9534    }
9535
9536    @Override
9537    public long computeBatteryUptime(long curTime, int which) {
9538        return mOnBatteryTimeBase.computeUptime(curTime, which);
9539    }
9540
9541    @Override
9542    public long computeBatteryRealtime(long curTime, int which) {
9543        return mOnBatteryTimeBase.computeRealtime(curTime, which);
9544    }
9545
9546    @Override
9547    public long computeBatteryScreenOffUptime(long curTime, int which) {
9548        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
9549    }
9550
9551    @Override
9552    public long computeBatteryScreenOffRealtime(long curTime, int which) {
9553        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
9554    }
9555
9556    private long computeTimePerLevel(long[] steps, int numSteps) {
9557        // For now we'll do a simple average across all steps.
9558        if (numSteps <= 0) {
9559            return -1;
9560        }
9561        long total = 0;
9562        for (int i=0; i<numSteps; i++) {
9563            total += steps[i] & STEP_LEVEL_TIME_MASK;
9564        }
9565        return total / numSteps;
9566        /*
9567        long[] buckets = new long[numSteps];
9568        int numBuckets = 0;
9569        int numToAverage = 4;
9570        int i = 0;
9571        while (i < numSteps) {
9572            long totalTime = 0;
9573            int num = 0;
9574            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
9575                totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
9576                num++;
9577            }
9578            buckets[numBuckets] = totalTime / num;
9579            numBuckets++;
9580            numToAverage *= 2;
9581            i += num;
9582        }
9583        if (numBuckets < 1) {
9584            return -1;
9585        }
9586        long averageTime = buckets[numBuckets-1];
9587        for (i=numBuckets-2; i>=0; i--) {
9588            averageTime = (averageTime + buckets[i]) / 2;
9589        }
9590        return averageTime;
9591        */
9592    }
9593
9594    @Override
9595    public long computeBatteryTimeRemaining(long curTime) {
9596        if (!mOnBattery) {
9597            return -1;
9598        }
9599        /* Simple implementation just looks at the average discharge per level across the
9600           entire sample period.
9601        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
9602        if (discharge < 2) {
9603            return -1;
9604        }
9605        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
9606        if (duration < 1000*1000) {
9607            return -1;
9608        }
9609        long usPerLevel = duration/discharge;
9610        return usPerLevel * mCurrentBatteryLevel;
9611        */
9612        if (mDischargeStepTracker.mNumStepDurations < 1) {
9613            return -1;
9614        }
9615        long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
9616        if (msPerLevel <= 0) {
9617            return -1;
9618        }
9619        return (msPerLevel * mCurrentBatteryLevel) * 1000;
9620    }
9621
9622    @Override
9623    public LevelStepTracker getDischargeLevelStepTracker() {
9624        return mDischargeStepTracker;
9625    }
9626
9627    @Override
9628    public LevelStepTracker getDailyDischargeLevelStepTracker() {
9629        return mDailyDischargeStepTracker;
9630    }
9631
9632    @Override
9633    public long computeChargeTimeRemaining(long curTime) {
9634        if (mOnBattery) {
9635            // Not yet working.
9636            return -1;
9637        }
9638        /* Broken
9639        int curLevel = mCurrentBatteryLevel;
9640        int plugLevel = mDischargePlugLevel;
9641        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
9642            return -1;
9643        }
9644        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
9645        if (duration < 1000*1000) {
9646            return -1;
9647        }
9648        long usPerLevel = duration/(curLevel-plugLevel);
9649        return usPerLevel * (100-curLevel);
9650        */
9651        if (mChargeStepTracker.mNumStepDurations < 1) {
9652            return -1;
9653        }
9654        long msPerLevel = mChargeStepTracker.computeTimePerLevel();
9655        if (msPerLevel <= 0) {
9656            return -1;
9657        }
9658        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
9659    }
9660
9661    @Override
9662    public LevelStepTracker getChargeLevelStepTracker() {
9663        return mChargeStepTracker;
9664    }
9665
9666    @Override
9667    public LevelStepTracker getDailyChargeLevelStepTracker() {
9668        return mDailyChargeStepTracker;
9669    }
9670
9671    @Override
9672    public ArrayList<PackageChange> getDailyPackageChanges() {
9673        return mDailyPackageChanges;
9674    }
9675
9676    protected long getBatteryUptimeLocked() {
9677        return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
9678    }
9679
9680    @Override
9681    public long getBatteryUptime(long curTime) {
9682        return mOnBatteryTimeBase.getUptime(curTime);
9683    }
9684
9685    @Override
9686    public long getBatteryRealtime(long curTime) {
9687        return mOnBatteryTimeBase.getRealtime(curTime);
9688    }
9689
9690    @Override
9691    public int getDischargeStartLevel() {
9692        synchronized(this) {
9693            return getDischargeStartLevelLocked();
9694        }
9695    }
9696
9697    public int getDischargeStartLevelLocked() {
9698            return mDischargeUnplugLevel;
9699    }
9700
9701    @Override
9702    public int getDischargeCurrentLevel() {
9703        synchronized(this) {
9704            return getDischargeCurrentLevelLocked();
9705        }
9706    }
9707
9708    public int getDischargeCurrentLevelLocked() {
9709        return mDischargeCurrentLevel;
9710    }
9711
9712    @Override
9713    public int getLowDischargeAmountSinceCharge() {
9714        synchronized(this) {
9715            int val = mLowDischargeAmountSinceCharge;
9716            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
9717                val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
9718            }
9719            return val;
9720        }
9721    }
9722
9723    @Override
9724    public int getHighDischargeAmountSinceCharge() {
9725        synchronized(this) {
9726            int val = mHighDischargeAmountSinceCharge;
9727            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
9728                val += mDischargeUnplugLevel-mDischargeCurrentLevel;
9729            }
9730            return val;
9731        }
9732    }
9733
9734    @Override
9735    public int getDischargeAmount(int which) {
9736        int dischargeAmount = which == STATS_SINCE_CHARGED
9737                ? getHighDischargeAmountSinceCharge()
9738                : (getDischargeStartLevel() - getDischargeCurrentLevel());
9739        if (dischargeAmount < 0) {
9740            dischargeAmount = 0;
9741        }
9742        return dischargeAmount;
9743    }
9744
9745    public int getDischargeAmountScreenOn() {
9746        synchronized(this) {
9747            int val = mDischargeAmountScreenOn;
9748            if (mOnBattery && mScreenState == Display.STATE_ON
9749                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
9750                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
9751            }
9752            return val;
9753        }
9754    }
9755
9756    public int getDischargeAmountScreenOnSinceCharge() {
9757        synchronized(this) {
9758            int val = mDischargeAmountScreenOnSinceCharge;
9759            if (mOnBattery && mScreenState == Display.STATE_ON
9760                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
9761                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
9762            }
9763            return val;
9764        }
9765    }
9766
9767    public int getDischargeAmountScreenOff() {
9768        synchronized(this) {
9769            int val = mDischargeAmountScreenOff;
9770            if (mOnBattery && mScreenState != Display.STATE_ON
9771                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
9772                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
9773            }
9774            return val;
9775        }
9776    }
9777
9778    public int getDischargeAmountScreenOffSinceCharge() {
9779        synchronized(this) {
9780            int val = mDischargeAmountScreenOffSinceCharge;
9781            if (mOnBattery && mScreenState != Display.STATE_ON
9782                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
9783                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
9784            }
9785            return val;
9786        }
9787    }
9788
9789    /**
9790     * Retrieve the statistics object for a particular uid, creating if needed.
9791     */
9792    public Uid getUidStatsLocked(int uid) {
9793        Uid u = mUidStats.get(uid);
9794        if (u == null) {
9795            u = new Uid(this, uid);
9796            mUidStats.put(uid, u);
9797        }
9798        return u;
9799    }
9800
9801    /**
9802     * Remove the statistics object for a particular uid.
9803     */
9804    public void removeUidStatsLocked(int uid) {
9805        mKernelUidCpuTimeReader.removeUid(uid);
9806        mUidStats.remove(uid);
9807    }
9808
9809    /**
9810     * Retrieve the statistics object for a particular process, creating
9811     * if needed.
9812     */
9813    public Uid.Proc getProcessStatsLocked(int uid, String name) {
9814        uid = mapUid(uid);
9815        Uid u = getUidStatsLocked(uid);
9816        return u.getProcessStatsLocked(name);
9817    }
9818
9819    /**
9820     * Retrieve the statistics object for a particular process, creating
9821     * if needed.
9822     */
9823    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
9824        uid = mapUid(uid);
9825        Uid u = getUidStatsLocked(uid);
9826        return u.getPackageStatsLocked(pkg);
9827    }
9828
9829    /**
9830     * Retrieve the statistics object for a particular service, creating
9831     * if needed.
9832     */
9833    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
9834        uid = mapUid(uid);
9835        Uid u = getUidStatsLocked(uid);
9836        return u.getServiceStatsLocked(pkg, name);
9837    }
9838
9839    public void shutdownLocked() {
9840        recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
9841        writeSyncLocked();
9842        mShuttingDown = true;
9843    }
9844
9845    Parcel mPendingWrite = null;
9846    final ReentrantLock mWriteLock = new ReentrantLock();
9847
9848    public void writeAsyncLocked() {
9849        writeLocked(false);
9850    }
9851
9852    public void writeSyncLocked() {
9853        writeLocked(true);
9854    }
9855
9856    void writeLocked(boolean sync) {
9857        if (mFile == null) {
9858            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
9859            return;
9860        }
9861
9862        if (mShuttingDown) {
9863            return;
9864        }
9865
9866        Parcel out = Parcel.obtain();
9867        writeSummaryToParcel(out, true);
9868        mLastWriteTime = mClocks.elapsedRealtime();
9869
9870        if (mPendingWrite != null) {
9871            mPendingWrite.recycle();
9872        }
9873        mPendingWrite = out;
9874
9875        if (sync) {
9876            commitPendingDataToDisk();
9877        } else {
9878            BackgroundThread.getHandler().post(new Runnable() {
9879                @Override public void run() {
9880                    commitPendingDataToDisk();
9881                }
9882            });
9883        }
9884    }
9885
9886    public void commitPendingDataToDisk() {
9887        final Parcel next;
9888        synchronized (this) {
9889            next = mPendingWrite;
9890            mPendingWrite = null;
9891            if (next == null) {
9892                return;
9893            }
9894
9895            mWriteLock.lock();
9896        }
9897
9898        try {
9899            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
9900            stream.write(next.marshall());
9901            stream.flush();
9902            FileUtils.sync(stream);
9903            stream.close();
9904            mFile.commit();
9905        } catch (IOException e) {
9906            Slog.w("BatteryStats", "Error writing battery statistics", e);
9907            mFile.rollback();
9908        } finally {
9909            next.recycle();
9910            mWriteLock.unlock();
9911        }
9912    }
9913
9914    public void readLocked() {
9915        if (mDailyFile != null) {
9916            readDailyStatsLocked();
9917        }
9918
9919        if (mFile == null) {
9920            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
9921            return;
9922        }
9923
9924        mUidStats.clear();
9925
9926        try {
9927            File file = mFile.chooseForRead();
9928            if (!file.exists()) {
9929                return;
9930            }
9931            FileInputStream stream = new FileInputStream(file);
9932
9933            byte[] raw = BatteryStatsHelper.readFully(stream);
9934            Parcel in = Parcel.obtain();
9935            in.unmarshall(raw, 0, raw.length);
9936            in.setDataPosition(0);
9937            stream.close();
9938
9939            readSummaryFromParcel(in);
9940        } catch(Exception e) {
9941            Slog.e("BatteryStats", "Error reading battery statistics", e);
9942            resetAllStatsLocked();
9943        }
9944
9945        mEndPlatformVersion = Build.ID;
9946
9947        if (mHistoryBuffer.dataPosition() > 0) {
9948            mRecordingHistory = true;
9949            final long elapsedRealtime = mClocks.elapsedRealtime();
9950            final long uptime = mClocks.uptimeMillis();
9951            if (USE_OLD_HISTORY) {
9952                addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
9953            }
9954            addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
9955            startRecordingHistory(elapsedRealtime, uptime, false);
9956        }
9957
9958        recordDailyStatsIfNeededLocked(false);
9959    }
9960
9961    public int describeContents() {
9962        return 0;
9963    }
9964
9965    void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
9966        final long historyBaseTime = in.readLong();
9967
9968        mHistoryBuffer.setDataSize(0);
9969        mHistoryBuffer.setDataPosition(0);
9970        mHistoryTagPool.clear();
9971        mNextHistoryTagIdx = 0;
9972        mNumHistoryTagChars = 0;
9973
9974        int numTags = in.readInt();
9975        for (int i=0; i<numTags; i++) {
9976            int idx = in.readInt();
9977            String str = in.readString();
9978            if (str == null) {
9979                throw new ParcelFormatException("null history tag string");
9980            }
9981            int uid = in.readInt();
9982            HistoryTag tag = new HistoryTag();
9983            tag.string = str;
9984            tag.uid = uid;
9985            tag.poolIdx = idx;
9986            mHistoryTagPool.put(tag, idx);
9987            if (idx >= mNextHistoryTagIdx) {
9988                mNextHistoryTagIdx = idx+1;
9989            }
9990            mNumHistoryTagChars += tag.string.length() + 1;
9991        }
9992
9993        int bufSize = in.readInt();
9994        int curPos = in.dataPosition();
9995        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
9996            throw new ParcelFormatException("File corrupt: history data buffer too large " +
9997                    bufSize);
9998        } else if ((bufSize&~3) != bufSize) {
9999            throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
10000                    bufSize);
10001        } else {
10002            if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
10003                    + " bytes at " + curPos);
10004            mHistoryBuffer.appendFrom(in, curPos, bufSize);
10005            in.setDataPosition(curPos + bufSize);
10006        }
10007
10008        if (andOldHistory) {
10009            readOldHistory(in);
10010        }
10011
10012        if (DEBUG_HISTORY) {
10013            StringBuilder sb = new StringBuilder(128);
10014            sb.append("****************** OLD mHistoryBaseTime: ");
10015            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10016            Slog.i(TAG, sb.toString());
10017        }
10018        mHistoryBaseTime = historyBaseTime;
10019        if (DEBUG_HISTORY) {
10020            StringBuilder sb = new StringBuilder(128);
10021            sb.append("****************** NEW mHistoryBaseTime: ");
10022            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10023            Slog.i(TAG, sb.toString());
10024        }
10025
10026        // We are just arbitrarily going to insert 1 minute from the sample of
10027        // the last run until samples in this run.
10028        if (mHistoryBaseTime > 0) {
10029            long oldnow = mClocks.elapsedRealtime();
10030            mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
10031            if (DEBUG_HISTORY) {
10032                StringBuilder sb = new StringBuilder(128);
10033                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
10034                TimeUtils.formatDuration(mHistoryBaseTime, sb);
10035                Slog.i(TAG, sb.toString());
10036            }
10037        }
10038    }
10039
10040    void readOldHistory(Parcel in) {
10041        if (!USE_OLD_HISTORY) {
10042            return;
10043        }
10044        mHistory = mHistoryEnd = mHistoryCache = null;
10045        long time;
10046        while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
10047            HistoryItem rec = new HistoryItem(time, in);
10048            addHistoryRecordLocked(rec);
10049        }
10050    }
10051
10052    void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
10053        if (DEBUG_HISTORY) {
10054            StringBuilder sb = new StringBuilder(128);
10055            sb.append("****************** WRITING mHistoryBaseTime: ");
10056            TimeUtils.formatDuration(mHistoryBaseTime, sb);
10057            sb.append(" mLastHistoryElapsedRealtime: ");
10058            TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
10059            Slog.i(TAG, sb.toString());
10060        }
10061        out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
10062        if (!inclData) {
10063            out.writeInt(0);
10064            out.writeInt(0);
10065            return;
10066        }
10067        out.writeInt(mHistoryTagPool.size());
10068        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
10069            HistoryTag tag = ent.getKey();
10070            out.writeInt(ent.getValue());
10071            out.writeString(tag.string);
10072            out.writeInt(tag.uid);
10073        }
10074        out.writeInt(mHistoryBuffer.dataSize());
10075        if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
10076                + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
10077        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
10078
10079        if (andOldHistory) {
10080            writeOldHistory(out);
10081        }
10082    }
10083
10084    void writeOldHistory(Parcel out) {
10085        if (!USE_OLD_HISTORY) {
10086            return;
10087        }
10088        HistoryItem rec = mHistory;
10089        while (rec != null) {
10090            if (rec.time >= 0) rec.writeToParcel(out, 0);
10091            rec = rec.next;
10092        }
10093        out.writeLong(-1);
10094    }
10095
10096    public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
10097        final int version = in.readInt();
10098        if (version != VERSION) {
10099            Slog.w("BatteryStats", "readFromParcel: version got " + version
10100                + ", expected " + VERSION + "; erasing old stats");
10101            return;
10102        }
10103
10104        readHistory(in, true);
10105
10106        mStartCount = in.readInt();
10107        mUptime = in.readLong();
10108        mRealtime = in.readLong();
10109        mStartClockTime = in.readLong();
10110        mStartPlatformVersion = in.readString();
10111        mEndPlatformVersion = in.readString();
10112        mOnBatteryTimeBase.readSummaryFromParcel(in);
10113        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
10114        mDischargeUnplugLevel = in.readInt();
10115        mDischargePlugLevel = in.readInt();
10116        mDischargeCurrentLevel = in.readInt();
10117        mCurrentBatteryLevel = in.readInt();
10118        mEstimatedBatteryCapacity = in.readInt();
10119        mLowDischargeAmountSinceCharge = in.readInt();
10120        mHighDischargeAmountSinceCharge = in.readInt();
10121        mDischargeAmountScreenOnSinceCharge = in.readInt();
10122        mDischargeAmountScreenOffSinceCharge = in.readInt();
10123        mDischargeStepTracker.readFromParcel(in);
10124        mChargeStepTracker.readFromParcel(in);
10125        mDailyDischargeStepTracker.readFromParcel(in);
10126        mDailyChargeStepTracker.readFromParcel(in);
10127        mDischargeCounter.readSummaryFromParcelLocked(in);
10128        mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
10129        int NPKG = in.readInt();
10130        if (NPKG > 0) {
10131            mDailyPackageChanges = new ArrayList<>(NPKG);
10132            while (NPKG > 0) {
10133                NPKG--;
10134                PackageChange pc = new PackageChange();
10135                pc.mPackageName = in.readString();
10136                pc.mUpdate = in.readInt() != 0;
10137                pc.mVersionCode = in.readInt();
10138                mDailyPackageChanges.add(pc);
10139            }
10140        } else {
10141            mDailyPackageChanges = null;
10142        }
10143        mDailyStartTime = in.readLong();
10144        mNextMinDailyDeadline = in.readLong();
10145        mNextMaxDailyDeadline = in.readLong();
10146
10147        mStartCount++;
10148
10149        mScreenState = Display.STATE_UNKNOWN;
10150        mScreenOnTimer.readSummaryFromParcelLocked(in);
10151        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10152            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
10153        }
10154        mInteractive = false;
10155        mInteractiveTimer.readSummaryFromParcelLocked(in);
10156        mPhoneOn = false;
10157        mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
10158        mLongestLightIdleTime = in.readLong();
10159        mLongestFullIdleTime = in.readLong();
10160        mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
10161        mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
10162        mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
10163        mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
10164        mPhoneOnTimer.readSummaryFromParcelLocked(in);
10165        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10166            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
10167        }
10168        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
10169        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10170            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
10171        }
10172        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10173            mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
10174            mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
10175        }
10176        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10177        mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
10178        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
10179        mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
10180        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
10181        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
10182        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10183        mWifiOn = false;
10184        mWifiOnTimer.readSummaryFromParcelLocked(in);
10185        mGlobalWifiRunning = false;
10186        mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
10187        for (int i=0; i<NUM_WIFI_STATES; i++) {
10188            mWifiStateTimer[i].readSummaryFromParcelLocked(in);
10189        }
10190        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10191            mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
10192        }
10193        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10194            mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
10195        }
10196        mWifiActivity.readSummaryFromParcel(in);
10197        mBluetoothActivity.readSummaryFromParcel(in);
10198        mModemActivity.readSummaryFromParcel(in);
10199        mHasWifiReporting = in.readInt() != 0;
10200        mHasBluetoothReporting = in.readInt() != 0;
10201        mHasModemReporting = in.readInt() != 0;
10202
10203        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
10204        mFlashlightOnNesting = 0;
10205        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
10206        mCameraOnNesting = 0;
10207        mCameraOnTimer.readSummaryFromParcelLocked(in);
10208        mBluetoothScanNesting = 0;
10209        mBluetoothScanTimer.readSummaryFromParcelLocked(in);
10210
10211        int NKW = in.readInt();
10212        if (NKW > 10000) {
10213            throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
10214        }
10215        for (int ikw = 0; ikw < NKW; ikw++) {
10216            if (in.readInt() != 0) {
10217                String kwltName = in.readString();
10218                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
10219            }
10220        }
10221
10222        int NWR = in.readInt();
10223        if (NWR > 10000) {
10224            throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
10225        }
10226        for (int iwr = 0; iwr < NWR; iwr++) {
10227            if (in.readInt() != 0) {
10228                String reasonName = in.readString();
10229                getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
10230            }
10231        }
10232
10233        final int NU = in.readInt();
10234        if (NU > 10000) {
10235            throw new ParcelFormatException("File corrupt: too many uids " + NU);
10236        }
10237        for (int iu = 0; iu < NU; iu++) {
10238            int uid = in.readInt();
10239            Uid u = new Uid(this, uid);
10240            mUidStats.put(uid, u);
10241
10242            u.mWifiRunning = false;
10243            if (in.readInt() != 0) {
10244                u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
10245            }
10246            u.mFullWifiLockOut = false;
10247            if (in.readInt() != 0) {
10248                u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
10249            }
10250            u.mWifiScanStarted = false;
10251            if (in.readInt() != 0) {
10252                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
10253            }
10254            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
10255            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
10256                if (in.readInt() != 0) {
10257                    u.makeWifiBatchedScanBin(i, null);
10258                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
10259                }
10260            }
10261            u.mWifiMulticastEnabled = false;
10262            if (in.readInt() != 0) {
10263                u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
10264            }
10265            if (in.readInt() != 0) {
10266                u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10267            }
10268            if (in.readInt() != 0) {
10269                u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10270            }
10271            if (in.readInt() != 0) {
10272                u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10273            }
10274            if (in.readInt() != 0) {
10275                u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
10276            }
10277            if (in.readInt() != 0) {
10278                u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
10279            }
10280            if (in.readInt() != 0) {
10281                u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
10282            }
10283            u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
10284            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
10285                if (in.readInt() != 0) {
10286                    u.makeProcessState(i, null);
10287                    u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
10288                }
10289            }
10290            if (in.readInt() != 0) {
10291                u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
10292            }
10293
10294            if (in.readInt() != 0) {
10295                if (u.mUserActivityCounters == null) {
10296                    u.initUserActivityLocked();
10297                }
10298                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
10299                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
10300                }
10301            }
10302
10303            if (in.readInt() != 0) {
10304                if (u.mNetworkByteActivityCounters == null) {
10305                    u.initNetworkActivityLocked();
10306                }
10307                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10308                    u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
10309                    u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
10310                }
10311                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
10312                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
10313            }
10314
10315            u.mUserCpuTime.readSummaryFromParcelLocked(in);
10316            u.mSystemCpuTime.readSummaryFromParcelLocked(in);
10317            u.mCpuPower.readSummaryFromParcelLocked(in);
10318
10319            if (in.readInt() != 0) {
10320                final int numClusters = in.readInt();
10321                if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
10322                    throw new ParcelFormatException("Incompatible cpu cluster arrangement");
10323                }
10324
10325                u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
10326                for (int cluster = 0; cluster < numClusters; cluster++) {
10327                    if (in.readInt() != 0) {
10328                        final int NSB = in.readInt();
10329                        if (mPowerProfile != null &&
10330                                mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
10331                            throw new ParcelFormatException("File corrupt: too many speed bins " +
10332                                    NSB);
10333                        }
10334
10335                        u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB];
10336                        for (int speed = 0; speed < NSB; speed++) {
10337                            if (in.readInt() != 0) {
10338                                u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter(
10339                                        mOnBatteryTimeBase);
10340                                u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in);
10341                            }
10342                        }
10343                    } else {
10344                        u.mCpuClusterSpeed[cluster] = null;
10345                    }
10346                }
10347            } else {
10348                u.mCpuClusterSpeed = null;
10349            }
10350
10351            int NW = in.readInt();
10352            if (NW > 100) {
10353                throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
10354            }
10355            for (int iw = 0; iw < NW; iw++) {
10356                String wlName = in.readString();
10357                u.readWakeSummaryFromParcelLocked(wlName, in);
10358            }
10359
10360            int NS = in.readInt();
10361            if (NS > 100) {
10362                throw new ParcelFormatException("File corrupt: too many syncs " + NS);
10363            }
10364            for (int is = 0; is < NS; is++) {
10365                String name = in.readString();
10366                u.readSyncSummaryFromParcelLocked(name, in);
10367            }
10368
10369            int NJ = in.readInt();
10370            if (NJ > 100) {
10371                throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
10372            }
10373            for (int ij = 0; ij < NJ; ij++) {
10374                String name = in.readString();
10375                u.readJobSummaryFromParcelLocked(name, in);
10376            }
10377
10378            int NP = in.readInt();
10379            if (NP > 1000) {
10380                throw new ParcelFormatException("File corrupt: too many sensors " + NP);
10381            }
10382            for (int is = 0; is < NP; is++) {
10383                int seNumber = in.readInt();
10384                if (in.readInt() != 0) {
10385                    u.getSensorTimerLocked(seNumber, true)
10386                            .readSummaryFromParcelLocked(in);
10387                }
10388            }
10389
10390            NP = in.readInt();
10391            if (NP > 1000) {
10392                throw new ParcelFormatException("File corrupt: too many processes " + NP);
10393            }
10394            for (int ip = 0; ip < NP; ip++) {
10395                String procName = in.readString();
10396                Uid.Proc p = u.getProcessStatsLocked(procName);
10397                p.mUserTime = p.mLoadedUserTime = in.readLong();
10398                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
10399                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
10400                p.mStarts = p.mLoadedStarts = in.readInt();
10401                p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
10402                p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
10403                p.readExcessivePowerFromParcelLocked(in);
10404            }
10405
10406            NP = in.readInt();
10407            if (NP > 10000) {
10408                throw new ParcelFormatException("File corrupt: too many packages " + NP);
10409            }
10410            for (int ip = 0; ip < NP; ip++) {
10411                String pkgName = in.readString();
10412                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
10413                final int NWA = in.readInt();
10414                if (NWA > 1000) {
10415                    throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
10416                }
10417                p.mWakeupAlarms.clear();
10418                for (int iwa=0; iwa<NWA; iwa++) {
10419                    String tag = in.readString();
10420                    Counter c = new Counter(mOnBatteryTimeBase);
10421                    c.readSummaryFromParcelLocked(in);
10422                    p.mWakeupAlarms.put(tag, c);
10423                }
10424                NS = in.readInt();
10425                if (NS > 1000) {
10426                    throw new ParcelFormatException("File corrupt: too many services " + NS);
10427                }
10428                for (int is = 0; is < NS; is++) {
10429                    String servName = in.readString();
10430                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
10431                    s.mStartTime = s.mLoadedStartTime = in.readLong();
10432                    s.mStarts = s.mLoadedStarts = in.readInt();
10433                    s.mLaunches = s.mLoadedLaunches = in.readInt();
10434                }
10435            }
10436        }
10437    }
10438
10439    /**
10440     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
10441     * disk.  This format does not allow a lossless round-trip.
10442     *
10443     * @param out the Parcel to be written to.
10444     */
10445    public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
10446        pullPendingStateUpdatesLocked();
10447
10448        // Pull the clock time.  This may update the time and make a new history entry
10449        // if we had originally pulled a time before the RTC was set.
10450        long startClockTime = getStartClockTime();
10451
10452        final long NOW_SYS = mClocks.uptimeMillis() * 1000;
10453        final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
10454
10455        out.writeInt(VERSION);
10456
10457        writeHistory(out, inclHistory, true);
10458
10459        out.writeInt(mStartCount);
10460        out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
10461        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
10462        out.writeLong(startClockTime);
10463        out.writeString(mStartPlatformVersion);
10464        out.writeString(mEndPlatformVersion);
10465        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
10466        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
10467        out.writeInt(mDischargeUnplugLevel);
10468        out.writeInt(mDischargePlugLevel);
10469        out.writeInt(mDischargeCurrentLevel);
10470        out.writeInt(mCurrentBatteryLevel);
10471        out.writeInt(mEstimatedBatteryCapacity);
10472        out.writeInt(getLowDischargeAmountSinceCharge());
10473        out.writeInt(getHighDischargeAmountSinceCharge());
10474        out.writeInt(getDischargeAmountScreenOnSinceCharge());
10475        out.writeInt(getDischargeAmountScreenOffSinceCharge());
10476        mDischargeStepTracker.writeToParcel(out);
10477        mChargeStepTracker.writeToParcel(out);
10478        mDailyDischargeStepTracker.writeToParcel(out);
10479        mDailyChargeStepTracker.writeToParcel(out);
10480        mDischargeCounter.writeSummaryFromParcelLocked(out);
10481        mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
10482        if (mDailyPackageChanges != null) {
10483            final int NPKG = mDailyPackageChanges.size();
10484            out.writeInt(NPKG);
10485            for (int i=0; i<NPKG; i++) {
10486                PackageChange pc = mDailyPackageChanges.get(i);
10487                out.writeString(pc.mPackageName);
10488                out.writeInt(pc.mUpdate ? 1 : 0);
10489                out.writeInt(pc.mVersionCode);
10490            }
10491        } else {
10492            out.writeInt(0);
10493        }
10494        out.writeLong(mDailyStartTime);
10495        out.writeLong(mNextMinDailyDeadline);
10496        out.writeLong(mNextMaxDailyDeadline);
10497
10498        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10499        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10500            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10501        }
10502        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10503        mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10504        out.writeLong(mLongestLightIdleTime);
10505        out.writeLong(mLongestFullIdleTime);
10506        mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10507        mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10508        mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10509        mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10510        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10511        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10512            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10513        }
10514        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10515        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10516            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10517        }
10518        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10519            mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
10520            mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
10521        }
10522        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10523        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10524        mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
10525        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
10526        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
10527        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10528        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10529        for (int i=0; i<NUM_WIFI_STATES; i++) {
10530            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10531        }
10532        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10533            mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10534        }
10535        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10536            mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10537        }
10538        mWifiActivity.writeSummaryToParcel(out);
10539        mBluetoothActivity.writeSummaryToParcel(out);
10540        mModemActivity.writeSummaryToParcel(out);
10541        out.writeInt(mHasWifiReporting ? 1 : 0);
10542        out.writeInt(mHasBluetoothReporting ? 1 : 0);
10543        out.writeInt(mHasModemReporting ? 1 : 0);
10544
10545        out.writeInt(mNumConnectivityChange);
10546        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10547        mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10548        mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10549
10550        out.writeInt(mKernelWakelockStats.size());
10551        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
10552            Timer kwlt = ent.getValue();
10553            if (kwlt != null) {
10554                out.writeInt(1);
10555                out.writeString(ent.getKey());
10556                kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10557            } else {
10558                out.writeInt(0);
10559            }
10560        }
10561
10562        out.writeInt(mWakeupReasonStats.size());
10563        for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
10564            SamplingTimer timer = ent.getValue();
10565            if (timer != null) {
10566                out.writeInt(1);
10567                out.writeString(ent.getKey());
10568                timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10569            } else {
10570                out.writeInt(0);
10571            }
10572        }
10573
10574        final int NU = mUidStats.size();
10575        out.writeInt(NU);
10576        for (int iu = 0; iu < NU; iu++) {
10577            out.writeInt(mUidStats.keyAt(iu));
10578            Uid u = mUidStats.valueAt(iu);
10579
10580            if (u.mWifiRunningTimer != null) {
10581                out.writeInt(1);
10582                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10583            } else {
10584                out.writeInt(0);
10585            }
10586            if (u.mFullWifiLockTimer != null) {
10587                out.writeInt(1);
10588                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10589            } else {
10590                out.writeInt(0);
10591            }
10592            if (u.mWifiScanTimer != null) {
10593                out.writeInt(1);
10594                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10595            } else {
10596                out.writeInt(0);
10597            }
10598            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
10599                if (u.mWifiBatchedScanTimer[i] != null) {
10600                    out.writeInt(1);
10601                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10602                } else {
10603                    out.writeInt(0);
10604                }
10605            }
10606            if (u.mWifiMulticastTimer != null) {
10607                out.writeInt(1);
10608                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10609            } else {
10610                out.writeInt(0);
10611            }
10612            if (u.mAudioTurnedOnTimer != null) {
10613                out.writeInt(1);
10614                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10615            } else {
10616                out.writeInt(0);
10617            }
10618            if (u.mVideoTurnedOnTimer != null) {
10619                out.writeInt(1);
10620                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10621            } else {
10622                out.writeInt(0);
10623            }
10624            if (u.mFlashlightTurnedOnTimer != null) {
10625                out.writeInt(1);
10626                u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10627            } else {
10628                out.writeInt(0);
10629            }
10630            if (u.mCameraTurnedOnTimer != null) {
10631                out.writeInt(1);
10632                u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10633            } else {
10634                out.writeInt(0);
10635            }
10636            if (u.mForegroundActivityTimer != null) {
10637                out.writeInt(1);
10638                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10639            } else {
10640                out.writeInt(0);
10641            }
10642            if (u.mBluetoothScanTimer != null) {
10643                out.writeInt(1);
10644                u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10645            } else {
10646                out.writeInt(0);
10647            }
10648            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
10649                if (u.mProcessStateTimer[i] != null) {
10650                    out.writeInt(1);
10651                    u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10652                } else {
10653                    out.writeInt(0);
10654                }
10655            }
10656            if (u.mVibratorOnTimer != null) {
10657                out.writeInt(1);
10658                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10659            } else {
10660                out.writeInt(0);
10661            }
10662
10663            if (u.mUserActivityCounters == null) {
10664                out.writeInt(0);
10665            } else {
10666                out.writeInt(1);
10667                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
10668                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
10669                }
10670            }
10671
10672            if (u.mNetworkByteActivityCounters == null) {
10673                out.writeInt(0);
10674            } else {
10675                out.writeInt(1);
10676                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10677                    u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
10678                    u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
10679                }
10680                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
10681                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
10682            }
10683
10684            u.mUserCpuTime.writeSummaryFromParcelLocked(out);
10685            u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
10686            u.mCpuPower.writeSummaryFromParcelLocked(out);
10687
10688            if (u.mCpuClusterSpeed != null) {
10689                out.writeInt(1);
10690                out.writeInt(u.mCpuClusterSpeed.length);
10691                for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) {
10692                    if (cpuSpeeds != null) {
10693                        out.writeInt(1);
10694                        out.writeInt(cpuSpeeds.length);
10695                        for (LongSamplingCounter c : cpuSpeeds) {
10696                            if (c != null) {
10697                                out.writeInt(1);
10698                                c.writeSummaryFromParcelLocked(out);
10699                            } else {
10700                                out.writeInt(0);
10701                            }
10702                        }
10703                    } else {
10704                        out.writeInt(0);
10705                    }
10706                }
10707            } else {
10708                out.writeInt(0);
10709            }
10710
10711            final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
10712            int NW = wakeStats.size();
10713            out.writeInt(NW);
10714            for (int iw=0; iw<NW; iw++) {
10715                out.writeString(wakeStats.keyAt(iw));
10716                Uid.Wakelock wl = wakeStats.valueAt(iw);
10717                if (wl.mTimerFull != null) {
10718                    out.writeInt(1);
10719                    wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10720                } else {
10721                    out.writeInt(0);
10722                }
10723                if (wl.mTimerPartial != null) {
10724                    out.writeInt(1);
10725                    wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10726                } else {
10727                    out.writeInt(0);
10728                }
10729                if (wl.mTimerWindow != null) {
10730                    out.writeInt(1);
10731                    wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10732                } else {
10733                    out.writeInt(0);
10734                }
10735                if (wl.mTimerDraw != null) {
10736                    out.writeInt(1);
10737                    wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10738                } else {
10739                    out.writeInt(0);
10740                }
10741            }
10742
10743            final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
10744            int NS = syncStats.size();
10745            out.writeInt(NS);
10746            for (int is=0; is<NS; is++) {
10747                out.writeString(syncStats.keyAt(is));
10748                syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10749            }
10750
10751            final ArrayMap<String, StopwatchTimer> jobStats = u.mJobStats.getMap();
10752            int NJ = jobStats.size();
10753            out.writeInt(NJ);
10754            for (int ij=0; ij<NJ; ij++) {
10755                out.writeString(jobStats.keyAt(ij));
10756                jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10757            }
10758
10759            int NSE = u.mSensorStats.size();
10760            out.writeInt(NSE);
10761            for (int ise=0; ise<NSE; ise++) {
10762                out.writeInt(u.mSensorStats.keyAt(ise));
10763                Uid.Sensor se = u.mSensorStats.valueAt(ise);
10764                if (se.mTimer != null) {
10765                    out.writeInt(1);
10766                    se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
10767                } else {
10768                    out.writeInt(0);
10769                }
10770            }
10771
10772            int NP = u.mProcessStats.size();
10773            out.writeInt(NP);
10774            for (int ip=0; ip<NP; ip++) {
10775                out.writeString(u.mProcessStats.keyAt(ip));
10776                Uid.Proc ps = u.mProcessStats.valueAt(ip);
10777                out.writeLong(ps.mUserTime);
10778                out.writeLong(ps.mSystemTime);
10779                out.writeLong(ps.mForegroundTime);
10780                out.writeInt(ps.mStarts);
10781                out.writeInt(ps.mNumCrashes);
10782                out.writeInt(ps.mNumAnrs);
10783                ps.writeExcessivePowerToParcelLocked(out);
10784            }
10785
10786            NP = u.mPackageStats.size();
10787            out.writeInt(NP);
10788            if (NP > 0) {
10789                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
10790                    : u.mPackageStats.entrySet()) {
10791                    out.writeString(ent.getKey());
10792                    Uid.Pkg ps = ent.getValue();
10793                    final int NWA = ps.mWakeupAlarms.size();
10794                    out.writeInt(NWA);
10795                    for (int iwa=0; iwa<NWA; iwa++) {
10796                        out.writeString(ps.mWakeupAlarms.keyAt(iwa));
10797                        ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
10798                    }
10799                    NS = ps.mServiceStats.size();
10800                    out.writeInt(NS);
10801                    for (int is=0; is<NS; is++) {
10802                        out.writeString(ps.mServiceStats.keyAt(is));
10803                        BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
10804                        long time = ss.getStartTimeToNowLocked(
10805                                mOnBatteryTimeBase.getUptime(NOW_SYS));
10806                        out.writeLong(time);
10807                        out.writeInt(ss.mStarts);
10808                        out.writeInt(ss.mLaunches);
10809                    }
10810                }
10811            }
10812        }
10813    }
10814
10815    public void readFromParcel(Parcel in) {
10816        readFromParcelLocked(in);
10817    }
10818
10819    void readFromParcelLocked(Parcel in) {
10820        int magic = in.readInt();
10821        if (magic != MAGIC) {
10822            throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
10823        }
10824
10825        readHistory(in, false);
10826
10827        mStartCount = in.readInt();
10828        mStartClockTime = in.readLong();
10829        mStartPlatformVersion = in.readString();
10830        mEndPlatformVersion = in.readString();
10831        mUptime = in.readLong();
10832        mUptimeStart = in.readLong();
10833        mRealtime = in.readLong();
10834        mRealtimeStart = in.readLong();
10835        mOnBattery = in.readInt() != 0;
10836        mEstimatedBatteryCapacity = in.readInt();
10837        mOnBatteryInternal = false; // we are no longer really running.
10838        mOnBatteryTimeBase.readFromParcel(in);
10839        mOnBatteryScreenOffTimeBase.readFromParcel(in);
10840
10841        mScreenState = Display.STATE_UNKNOWN;
10842        mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
10843        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10844            mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
10845                    mOnBatteryTimeBase, in);
10846        }
10847        mInteractive = false;
10848        mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
10849        mPhoneOn = false;
10850        mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
10851                mOnBatteryTimeBase, in);
10852        mLongestLightIdleTime = in.readLong();
10853        mLongestFullIdleTime = in.readLong();
10854        mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
10855                mOnBatteryTimeBase, in);
10856        mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
10857                mOnBatteryTimeBase, in);
10858        mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
10859                mOnBatteryTimeBase, in);
10860        mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
10861        mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
10862        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10863            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
10864                    null, mOnBatteryTimeBase, in);
10865        }
10866        mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
10867                mOnBatteryTimeBase, in);
10868        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10869            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
10870                    null, mOnBatteryTimeBase, in);
10871        }
10872        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10873            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
10874            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
10875        }
10876        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10877        mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
10878                mOnBatteryTimeBase, in);
10879        mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
10880                mOnBatteryTimeBase, in);
10881        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
10882        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
10883        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
10884        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
10885        mWifiOn = false;
10886        mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
10887        mGlobalWifiRunning = false;
10888        mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
10889                mOnBatteryTimeBase, in);
10890        for (int i=0; i<NUM_WIFI_STATES; i++) {
10891            mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
10892                    null, mOnBatteryTimeBase, in);
10893        }
10894        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10895            mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
10896                    null, mOnBatteryTimeBase, in);
10897        }
10898        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10899            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
10900                    null, mOnBatteryTimeBase, in);
10901        }
10902
10903        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10904                NUM_WIFI_TX_LEVELS, in);
10905        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10906                NUM_BT_TX_LEVELS, in);
10907        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
10908                ModemActivityInfo.TX_POWER_LEVELS, in);
10909        mHasWifiReporting = in.readInt() != 0;
10910        mHasBluetoothReporting = in.readInt() != 0;
10911        mHasModemReporting = in.readInt() != 0;
10912
10913        mNumConnectivityChange = in.readInt();
10914        mLoadedNumConnectivityChange = in.readInt();
10915        mUnpluggedNumConnectivityChange = in.readInt();
10916        mAudioOnNesting = 0;
10917        mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
10918        mVideoOnNesting = 0;
10919        mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
10920        mFlashlightOnNesting = 0;
10921        mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
10922        mCameraOnNesting = 0;
10923        mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
10924        mBluetoothScanNesting = 0;
10925        mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
10926        mDischargeUnplugLevel = in.readInt();
10927        mDischargePlugLevel = in.readInt();
10928        mDischargeCurrentLevel = in.readInt();
10929        mCurrentBatteryLevel = in.readInt();
10930        mLowDischargeAmountSinceCharge = in.readInt();
10931        mHighDischargeAmountSinceCharge = in.readInt();
10932        mDischargeAmountScreenOn = in.readInt();
10933        mDischargeAmountScreenOnSinceCharge = in.readInt();
10934        mDischargeAmountScreenOff = in.readInt();
10935        mDischargeAmountScreenOffSinceCharge = in.readInt();
10936        mDischargeStepTracker.readFromParcel(in);
10937        mChargeStepTracker.readFromParcel(in);
10938        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
10939        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
10940        mLastWriteTime = in.readLong();
10941
10942        mKernelWakelockStats.clear();
10943        int NKW = in.readInt();
10944        for (int ikw = 0; ikw < NKW; ikw++) {
10945            if (in.readInt() != 0) {
10946                String wakelockName = in.readString();
10947                SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
10948                mKernelWakelockStats.put(wakelockName, kwlt);
10949            }
10950        }
10951
10952        mWakeupReasonStats.clear();
10953        int NWR = in.readInt();
10954        for (int iwr = 0; iwr < NWR; iwr++) {
10955            if (in.readInt() != 0) {
10956                String reasonName = in.readString();
10957                SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
10958                mWakeupReasonStats.put(reasonName, timer);
10959            }
10960        }
10961
10962        mPartialTimers.clear();
10963        mFullTimers.clear();
10964        mWindowTimers.clear();
10965        mWifiRunningTimers.clear();
10966        mFullWifiLockTimers.clear();
10967        mWifiScanTimers.clear();
10968        mWifiBatchedScanTimers.clear();
10969        mWifiMulticastTimers.clear();
10970        mAudioTurnedOnTimers.clear();
10971        mVideoTurnedOnTimers.clear();
10972        mFlashlightTurnedOnTimers.clear();
10973        mCameraTurnedOnTimers.clear();
10974
10975        int numUids = in.readInt();
10976        mUidStats.clear();
10977        for (int i = 0; i < numUids; i++) {
10978            int uid = in.readInt();
10979            Uid u = new Uid(this, uid);
10980            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
10981            mUidStats.append(uid, u);
10982        }
10983    }
10984
10985    public void writeToParcel(Parcel out, int flags) {
10986        writeToParcelLocked(out, true, flags);
10987    }
10988
10989    public void writeToParcelWithoutUids(Parcel out, int flags) {
10990        writeToParcelLocked(out, false, flags);
10991    }
10992
10993    @SuppressWarnings("unused")
10994    void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
10995        // Need to update with current kernel wake lock counts.
10996        pullPendingStateUpdatesLocked();
10997
10998        // Pull the clock time.  This may update the time and make a new history entry
10999        // if we had originally pulled a time before the RTC was set.
11000        long startClockTime = getStartClockTime();
11001
11002        final long uSecUptime = mClocks.uptimeMillis() * 1000;
11003        final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
11004        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
11005        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
11006
11007        out.writeInt(MAGIC);
11008
11009        writeHistory(out, true, false);
11010
11011        out.writeInt(mStartCount);
11012        out.writeLong(startClockTime);
11013        out.writeString(mStartPlatformVersion);
11014        out.writeString(mEndPlatformVersion);
11015        out.writeLong(mUptime);
11016        out.writeLong(mUptimeStart);
11017        out.writeLong(mRealtime);
11018        out.writeLong(mRealtimeStart);
11019        out.writeInt(mOnBattery ? 1 : 0);
11020        out.writeInt(mEstimatedBatteryCapacity);
11021        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
11022        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
11023
11024        mScreenOnTimer.writeToParcel(out, uSecRealtime);
11025        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11026            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
11027        }
11028        mInteractiveTimer.writeToParcel(out, uSecRealtime);
11029        mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
11030        out.writeLong(mLongestLightIdleTime);
11031        out.writeLong(mLongestFullIdleTime);
11032        mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
11033        mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
11034        mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
11035        mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
11036        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
11037        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11038            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
11039        }
11040        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
11041        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11042            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
11043        }
11044        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
11045            mNetworkByteActivityCounters[i].writeToParcel(out);
11046            mNetworkPacketActivityCounters[i].writeToParcel(out);
11047        }
11048        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
11049        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
11050        mMobileRadioActiveAdjustedTime.writeToParcel(out);
11051        mMobileRadioActiveUnknownTime.writeToParcel(out);
11052        mMobileRadioActiveUnknownCount.writeToParcel(out);
11053        mWifiOnTimer.writeToParcel(out, uSecRealtime);
11054        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
11055        for (int i=0; i<NUM_WIFI_STATES; i++) {
11056            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
11057        }
11058        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11059            mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
11060        }
11061        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11062            mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
11063        }
11064        mWifiActivity.writeToParcel(out, 0);
11065        mBluetoothActivity.writeToParcel(out, 0);
11066        mModemActivity.writeToParcel(out, 0);
11067        out.writeInt(mHasWifiReporting ? 1 : 0);
11068        out.writeInt(mHasBluetoothReporting ? 1 : 0);
11069        out.writeInt(mHasModemReporting ? 1 : 0);
11070
11071        out.writeInt(mNumConnectivityChange);
11072        out.writeInt(mLoadedNumConnectivityChange);
11073        out.writeInt(mUnpluggedNumConnectivityChange);
11074        mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
11075        mCameraOnTimer.writeToParcel(out, uSecRealtime);
11076        mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
11077        out.writeInt(mDischargeUnplugLevel);
11078        out.writeInt(mDischargePlugLevel);
11079        out.writeInt(mDischargeCurrentLevel);
11080        out.writeInt(mCurrentBatteryLevel);
11081        out.writeInt(mLowDischargeAmountSinceCharge);
11082        out.writeInt(mHighDischargeAmountSinceCharge);
11083        out.writeInt(mDischargeAmountScreenOn);
11084        out.writeInt(mDischargeAmountScreenOnSinceCharge);
11085        out.writeInt(mDischargeAmountScreenOff);
11086        out.writeInt(mDischargeAmountScreenOffSinceCharge);
11087        mDischargeStepTracker.writeToParcel(out);
11088        mChargeStepTracker.writeToParcel(out);
11089        mDischargeCounter.writeToParcel(out);
11090        mDischargeScreenOffCounter.writeToParcel(out);
11091        out.writeLong(mLastWriteTime);
11092
11093        if (inclUids) {
11094            out.writeInt(mKernelWakelockStats.size());
11095            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
11096                SamplingTimer kwlt = ent.getValue();
11097                if (kwlt != null) {
11098                    out.writeInt(1);
11099                    out.writeString(ent.getKey());
11100                    kwlt.writeToParcel(out, uSecRealtime);
11101                } else {
11102                    out.writeInt(0);
11103                }
11104            }
11105            out.writeInt(mWakeupReasonStats.size());
11106            for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
11107                SamplingTimer timer = ent.getValue();
11108                if (timer != null) {
11109                    out.writeInt(1);
11110                    out.writeString(ent.getKey());
11111                    timer.writeToParcel(out, uSecRealtime);
11112                } else {
11113                    out.writeInt(0);
11114                }
11115            }
11116        } else {
11117            out.writeInt(0);
11118        }
11119
11120        if (inclUids) {
11121            int size = mUidStats.size();
11122            out.writeInt(size);
11123            for (int i = 0; i < size; i++) {
11124                out.writeInt(mUidStats.keyAt(i));
11125                Uid uid = mUidStats.valueAt(i);
11126
11127                uid.writeToParcelLocked(out, uSecRealtime);
11128            }
11129        } else {
11130            out.writeInt(0);
11131        }
11132    }
11133
11134    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
11135        new Parcelable.Creator<BatteryStatsImpl>() {
11136        public BatteryStatsImpl createFromParcel(Parcel in) {
11137            return new BatteryStatsImpl(in);
11138        }
11139
11140        public BatteryStatsImpl[] newArray(int size) {
11141            return new BatteryStatsImpl[size];
11142        }
11143    };
11144
11145    public void prepareForDumpLocked() {
11146        // Need to retrieve current kernel wake lock stats before printing.
11147        pullPendingStateUpdatesLocked();
11148
11149        // Pull the clock time.  This may update the time and make a new history entry
11150        // if we had originally pulled a time before the RTC was set.
11151        getStartClockTime();
11152    }
11153
11154    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
11155        if (DEBUG) {
11156            pw.println("mOnBatteryTimeBase:");
11157            mOnBatteryTimeBase.dump(pw, "  ");
11158            pw.println("mOnBatteryScreenOffTimeBase:");
11159            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
11160            Printer pr = new PrintWriterPrinter(pw);
11161            pr.println("*** Screen timer:");
11162            mScreenOnTimer.logState(pr, "  ");
11163            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
11164                pr.println("*** Screen brightness #" + i + ":");
11165                mScreenBrightnessTimer[i].logState(pr, "  ");
11166            }
11167            pr.println("*** Interactive timer:");
11168            mInteractiveTimer.logState(pr, "  ");
11169            pr.println("*** Power save mode timer:");
11170            mPowerSaveModeEnabledTimer.logState(pr, "  ");
11171            pr.println("*** Device idle mode light timer:");
11172            mDeviceIdleModeLightTimer.logState(pr, "  ");
11173            pr.println("*** Device idle mode full timer:");
11174            mDeviceIdleModeFullTimer.logState(pr, "  ");
11175            pr.println("*** Device light idling timer:");
11176            mDeviceLightIdlingTimer.logState(pr, "  ");
11177            pr.println("*** Device idling timer:");
11178            mDeviceIdlingTimer.logState(pr, "  ");
11179            pr.println("*** Phone timer:");
11180            mPhoneOnTimer.logState(pr, "  ");
11181            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
11182                pr.println("*** Phone signal strength #" + i + ":");
11183                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
11184            }
11185            pr.println("*** Signal scanning :");
11186            mPhoneSignalScanningTimer.logState(pr, "  ");
11187            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
11188                pr.println("*** Data connection type #" + i + ":");
11189                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
11190            }
11191            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
11192            pr.println("*** Mobile network active timer:");
11193            mMobileRadioActiveTimer.logState(pr, "  ");
11194            pr.println("*** Mobile network active adjusted timer:");
11195            mMobileRadioActiveAdjustedTime.logState(pr, "  ");
11196            pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
11197            pr.println("*** Wifi timer:");
11198            mWifiOnTimer.logState(pr, "  ");
11199            pr.println("*** WifiRunning timer:");
11200            mGlobalWifiRunningTimer.logState(pr, "  ");
11201            for (int i=0; i<NUM_WIFI_STATES; i++) {
11202                pr.println("*** Wifi state #" + i + ":");
11203                mWifiStateTimer[i].logState(pr, "  ");
11204            }
11205            for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
11206                pr.println("*** Wifi suppl state #" + i + ":");
11207                mWifiSupplStateTimer[i].logState(pr, "  ");
11208            }
11209            for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
11210                pr.println("*** Wifi signal strength #" + i + ":");
11211                mWifiSignalStrengthsTimer[i].logState(pr, "  ");
11212            }
11213            pr.println("*** Flashlight timer:");
11214            mFlashlightOnTimer.logState(pr, "  ");
11215            pr.println("*** Camera timer:");
11216            mCameraOnTimer.logState(pr, "  ");
11217        }
11218        super.dumpLocked(context, pw, flags, reqUid, histStart);
11219    }
11220}
11221