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