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