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