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