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