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.BatteryManager;
29import android.os.BatteryStats;
30import android.os.Build;
31import android.os.FileUtils;
32import android.os.Handler;
33import android.os.Looper;
34import android.os.Message;
35import android.os.Parcel;
36import android.os.ParcelFormatException;
37import android.os.Parcelable;
38import android.os.Process;
39import android.os.SystemClock;
40import android.os.SystemProperties;
41import android.os.WorkSource;
42import android.telephony.DataConnectionRealTimeInfo;
43import android.telephony.ServiceState;
44import android.telephony.SignalStrength;
45import android.telephony.TelephonyManager;
46import android.text.TextUtils;
47import android.util.ArrayMap;
48import android.util.Log;
49import android.util.LogWriter;
50import android.util.MutableInt;
51import android.util.PrintWriterPrinter;
52import android.util.Printer;
53import android.util.Slog;
54import android.util.SparseArray;
55import android.util.SparseIntArray;
56import android.util.SparseLongArray;
57import android.util.TimeUtils;
58import android.util.Xml;
59import android.view.Display;
60
61import com.android.internal.net.NetworkStatsFactory;
62import com.android.internal.util.ArrayUtils;
63import com.android.internal.util.FastPrintWriter;
64import com.android.internal.util.FastXmlSerializer;
65import com.android.internal.util.JournaledFile;
66import com.android.internal.util.XmlUtils;
67import com.android.server.NetworkManagementSocketTagger;
68import libcore.util.EmptyArray;
69import org.xmlpull.v1.XmlPullParser;
70import org.xmlpull.v1.XmlPullParserException;
71import org.xmlpull.v1.XmlSerializer;
72
73import java.io.ByteArrayOutputStream;
74import java.io.File;
75import java.io.FileInputStream;
76import java.io.FileNotFoundException;
77import java.io.FileOutputStream;
78import java.io.IOException;
79import java.io.PrintWriter;
80import java.nio.charset.StandardCharsets;
81import java.util.ArrayList;
82import java.util.Calendar;
83import java.util.HashMap;
84import java.util.Iterator;
85import java.util.Map;
86import java.util.concurrent.atomic.AtomicInteger;
87import java.util.concurrent.locks.ReentrantLock;
88
89/**
90 * All information we are collecting about things that can happen that impact
91 * battery life.  All times are represented in microseconds except where indicated
92 * otherwise.
93 */
94public final class BatteryStatsImpl extends BatteryStats {
95    private static final String TAG = "BatteryStatsImpl";
96    private static final boolean DEBUG = false;
97    public static final boolean DEBUG_ENERGY = false;
98    private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false;
99    private static final boolean DEBUG_HISTORY = false;
100    private static final boolean USE_OLD_HISTORY = false;   // for debugging.
101
102    // TODO: remove "tcp" from network methods, since we measure total stats.
103
104    // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
105    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
106
107    // Current on-disk Parcel version
108    private static final int VERSION = 132 + (USE_OLD_HISTORY ? 1000 : 0);
109
110    // Maximum number of items we will record in the history.
111    private static final int MAX_HISTORY_ITEMS = 2000;
112
113    // No, really, THIS is the maximum number of items we will record in the history.
114    private static final int MAX_MAX_HISTORY_ITEMS = 3000;
115
116    // The maximum number of names wakelocks we will keep track of
117    // per uid; once the limit is reached, we batch the remaining wakelocks
118    // in to one common name.
119    private static final int MAX_WAKELOCKS_PER_UID = 100;
120
121    private final JournaledFile mFile;
122    public final AtomicFile mCheckinFile;
123    public final AtomicFile mDailyFile;
124
125    static final int MSG_UPDATE_WAKELOCKS = 1;
126    static final int MSG_REPORT_POWER_CHANGE = 2;
127    static final int MSG_REPORT_CHARGING = 3;
128    static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
129
130    private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
131    private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
132
133    private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
134    private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
135
136    public interface BatteryCallback {
137        public void batteryNeedsCpuUpdate();
138        public void batteryPowerChanged(boolean onBattery);
139        public void batterySendBroadcast(Intent intent);
140    }
141
142    final class MyHandler extends Handler {
143        public MyHandler(Looper looper) {
144            super(looper, null, true);
145        }
146
147        @Override
148        public void handleMessage(Message msg) {
149            BatteryCallback cb = mCallback;
150            switch (msg.what) {
151                case MSG_UPDATE_WAKELOCKS:
152                    synchronized (BatteryStatsImpl.this) {
153                        updateCpuTimeLocked();
154                    }
155                    if (cb != null) {
156                        cb.batteryNeedsCpuUpdate();
157                    }
158                    break;
159                case MSG_REPORT_POWER_CHANGE:
160                    if (cb != null) {
161                        cb.batteryPowerChanged(msg.arg1 != 0);
162                    }
163                    break;
164                case MSG_REPORT_CHARGING:
165                    if (cb != null) {
166                        final String action;
167                        synchronized (BatteryStatsImpl.this) {
168                            action = mCharging ? BatteryManager.ACTION_CHARGING
169                                    : BatteryManager.ACTION_DISCHARGING;
170                        }
171                        Intent intent = new Intent(action);
172                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
173                        cb.batterySendBroadcast(intent);
174                    }
175                    break;
176            }
177        }
178    }
179
180    public interface ExternalStatsSync {
181        void scheduleSync(String reason);
182        void scheduleWifiSync(String reason);
183        void scheduleCpuSyncDueToRemovedUid(int uid);
184    }
185
186    public final MyHandler mHandler;
187    private final ExternalStatsSync mExternalSync;
188
189    private BatteryCallback mCallback;
190
191    /**
192     * Mapping isolated uids to the actual owning app uid.
193     */
194    final SparseIntArray mIsolatedUids = new SparseIntArray();
195
196    /**
197     * The statistics we have collected organized by uids.
198     */
199    final SparseArray<BatteryStatsImpl.Uid> mUidStats =
200        new SparseArray<BatteryStatsImpl.Uid>();
201
202    // A set of pools of currently active timers.  When a timer is queried, we will divide the
203    // elapsed time by the number of active timers to arrive at that timer's share of the time.
204    // In order to do this, we must refresh each timer whenever the number of active timers
205    // changes.
206    final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
207    final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
208    final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
209    final ArrayList<StopwatchTimer> mDrawTimers = 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    /**
2524     * Schedules a read of the latest cpu times before removing the isolated UID.
2525     * @see #removeIsolatedUidLocked(int)
2526     */
2527    public void scheduleRemoveIsolatedUidLocked(int isolatedUid, int appUid) {
2528        int curUid = mIsolatedUids.get(isolatedUid, -1);
2529        if (curUid == appUid) {
2530            if (mExternalSync != null) {
2531                mExternalSync.scheduleCpuSyncDueToRemovedUid(isolatedUid);
2532            }
2533        }
2534    }
2535
2536    /**
2537     * This should only be called after the cpu times have been read.
2538     * @see #scheduleRemoveIsolatedUidLocked(int, int)
2539     */
2540    public void removeIsolatedUidLocked(int isolatedUid) {
2541        mIsolatedUids.delete(isolatedUid);
2542        mKernelUidCpuTimeReader.removeUid(isolatedUid);
2543    }
2544
2545    public int mapUid(int uid) {
2546        int isolated = mIsolatedUids.get(uid, -1);
2547        return isolated > 0 ? isolated : uid;
2548    }
2549
2550    public void noteEventLocked(int code, String name, int uid) {
2551        uid = mapUid(uid);
2552        if (!mActiveEvents.updateState(code, name, uid, 0)) {
2553            return;
2554        }
2555        final long elapsedRealtime = SystemClock.elapsedRealtime();
2556        final long uptime = SystemClock.uptimeMillis();
2557        addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
2558    }
2559
2560    boolean ensureStartClockTime(final long currentTime) {
2561        final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
2562        if (currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR)) {
2563            // If the start clock time has changed by more than a year, then presumably
2564            // the previous time was completely bogus.  So we are going to figure out a
2565            // new time based on how much time has elapsed since we started counting.
2566            mStartClockTime = currentTime - (SystemClock.elapsedRealtime()-(mRealtimeStart/1000));
2567            return true;
2568        }
2569        return false;
2570    }
2571
2572    public void noteCurrentTimeChangedLocked() {
2573        final long currentTime = System.currentTimeMillis();
2574        final long elapsedRealtime = SystemClock.elapsedRealtime();
2575        final long uptime = SystemClock.uptimeMillis();
2576        recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
2577        ensureStartClockTime(currentTime);
2578    }
2579
2580    public void noteProcessStartLocked(String name, int uid) {
2581        uid = mapUid(uid);
2582        if (isOnBattery()) {
2583            Uid u = getUidStatsLocked(uid);
2584            u.getProcessStatsLocked(name).incStartsLocked();
2585        }
2586        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) {
2587            return;
2588        }
2589        if (!mRecordAllHistory) {
2590            return;
2591        }
2592        final long elapsedRealtime = SystemClock.elapsedRealtime();
2593        final long uptime = SystemClock.uptimeMillis();
2594        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
2595    }
2596
2597    public void noteProcessCrashLocked(String name, int uid) {
2598        uid = mapUid(uid);
2599        if (isOnBattery()) {
2600            Uid u = getUidStatsLocked(uid);
2601            u.getProcessStatsLocked(name).incNumCrashesLocked();
2602        }
2603    }
2604
2605    public void noteProcessAnrLocked(String name, int uid) {
2606        uid = mapUid(uid);
2607        if (isOnBattery()) {
2608            Uid u = getUidStatsLocked(uid);
2609            u.getProcessStatsLocked(name).incNumAnrsLocked();
2610        }
2611    }
2612
2613    public void noteProcessStateLocked(String name, int uid, int state) {
2614        uid = mapUid(uid);
2615        final long elapsedRealtime = SystemClock.elapsedRealtime();
2616        getUidStatsLocked(uid).updateProcessStateLocked(name, state, elapsedRealtime);
2617    }
2618
2619    public void noteProcessFinishLocked(String name, int uid) {
2620        uid = mapUid(uid);
2621        if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
2622            return;
2623        }
2624        final long elapsedRealtime = SystemClock.elapsedRealtime();
2625        final long uptime = SystemClock.uptimeMillis();
2626        getUidStatsLocked(uid).updateProcessStateLocked(name, Uid.PROCESS_STATE_NONE,
2627                elapsedRealtime);
2628        if (!mRecordAllHistory) {
2629            return;
2630        }
2631        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
2632    }
2633
2634    public void noteSyncStartLocked(String name, int uid) {
2635        uid = mapUid(uid);
2636        final long elapsedRealtime = SystemClock.elapsedRealtime();
2637        final long uptime = SystemClock.uptimeMillis();
2638        getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
2639        if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
2640            return;
2641        }
2642        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
2643    }
2644
2645    public void noteSyncFinishLocked(String name, int uid) {
2646        uid = mapUid(uid);
2647        final long elapsedRealtime = SystemClock.elapsedRealtime();
2648        final long uptime = SystemClock.uptimeMillis();
2649        getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
2650        if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
2651            return;
2652        }
2653        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
2654    }
2655
2656    public void noteJobStartLocked(String name, int uid) {
2657        uid = mapUid(uid);
2658        final long elapsedRealtime = SystemClock.elapsedRealtime();
2659        final long uptime = SystemClock.uptimeMillis();
2660        getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
2661        if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
2662            return;
2663        }
2664        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
2665    }
2666
2667    public void noteJobFinishLocked(String name, int uid) {
2668        uid = mapUid(uid);
2669        final long elapsedRealtime = SystemClock.elapsedRealtime();
2670        final long uptime = SystemClock.uptimeMillis();
2671        getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
2672        if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
2673            return;
2674        }
2675        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
2676    }
2677
2678    public void noteAlarmStartLocked(String name, int uid) {
2679        if (!mRecordAllHistory) {
2680            return;
2681        }
2682        uid = mapUid(uid);
2683        final long elapsedRealtime = SystemClock.elapsedRealtime();
2684        final long uptime = SystemClock.uptimeMillis();
2685        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_START, name, uid, 0)) {
2686            return;
2687        }
2688        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_START, name, uid);
2689    }
2690
2691    public void noteAlarmFinishLocked(String name, int uid) {
2692        if (!mRecordAllHistory) {
2693            return;
2694        }
2695        uid = mapUid(uid);
2696        final long elapsedRealtime = SystemClock.elapsedRealtime();
2697        final long uptime = SystemClock.uptimeMillis();
2698        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_FINISH, name, uid, 0)) {
2699            return;
2700        }
2701        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_FINISH, name, uid);
2702    }
2703
2704    private void requestWakelockCpuUpdate() {
2705        if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
2706            Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
2707            mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
2708        }
2709    }
2710
2711    private void requestImmediateCpuUpdate() {
2712        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
2713        mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
2714    }
2715
2716    public void setRecordAllHistoryLocked(boolean enabled) {
2717        mRecordAllHistory = enabled;
2718        if (!enabled) {
2719            // Clear out any existing state.
2720            mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK);
2721            mActiveEvents.removeEvents(HistoryItem.EVENT_ALARM);
2722            // Record the currently running processes as stopping, now that we are no
2723            // longer tracking them.
2724            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
2725                    HistoryItem.EVENT_PROC);
2726            if (active != null) {
2727                long mSecRealtime = SystemClock.elapsedRealtime();
2728                final long mSecUptime = SystemClock.uptimeMillis();
2729                for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
2730                    SparseIntArray uids = ent.getValue();
2731                    for (int j=0; j<uids.size(); j++) {
2732                        addHistoryEventLocked(mSecRealtime, mSecUptime,
2733                                HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
2734                    }
2735                }
2736            }
2737        } else {
2738            // Record the currently running processes as starting, now that we are tracking them.
2739            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
2740                    HistoryItem.EVENT_PROC);
2741            if (active != null) {
2742                long mSecRealtime = SystemClock.elapsedRealtime();
2743                final long mSecUptime = SystemClock.uptimeMillis();
2744                for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
2745                    SparseIntArray uids = ent.getValue();
2746                    for (int j=0; j<uids.size(); j++) {
2747                        addHistoryEventLocked(mSecRealtime, mSecUptime,
2748                                HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
2749                    }
2750                }
2751            }
2752        }
2753    }
2754
2755    public void setNoAutoReset(boolean enabled) {
2756        mNoAutoReset = enabled;
2757    }
2758
2759    private String mInitialAcquireWakeName;
2760    private int mInitialAcquireWakeUid = -1;
2761
2762    public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
2763            boolean unimportantForLogging, long elapsedRealtime, long uptime) {
2764        uid = mapUid(uid);
2765        if (type == WAKE_TYPE_PARTIAL) {
2766            // Only care about partial wake locks, since full wake locks
2767            // will be canceled when the user puts the screen to sleep.
2768            aggregateLastWakeupUptimeLocked(uptime);
2769            if (historyName == null) {
2770                historyName = name;
2771            }
2772            if (mRecordAllHistory) {
2773                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
2774                        uid, 0)) {
2775                    addHistoryEventLocked(elapsedRealtime, uptime,
2776                            HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
2777                }
2778            }
2779            if (mWakeLockNesting == 0) {
2780                mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
2781                if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
2782                        + Integer.toHexString(mHistoryCur.states));
2783                mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
2784                mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
2785                mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
2786                mWakeLockImportant = !unimportantForLogging;
2787                addHistoryRecordLocked(elapsedRealtime, uptime);
2788            } else if (!mWakeLockImportant && !unimportantForLogging
2789                    && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
2790                if (mHistoryLastWritten.wakelockTag != null) {
2791                    // We'll try to update the last tag.
2792                    mHistoryLastWritten.wakelockTag = null;
2793                    mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
2794                    mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName;
2795                    mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
2796                    addHistoryRecordLocked(elapsedRealtime, uptime);
2797                }
2798                mWakeLockImportant = true;
2799            }
2800            mWakeLockNesting++;
2801        }
2802        if (uid >= 0) {
2803            if (mOnBatteryScreenOffTimeBase.isRunning()) {
2804                // We only update the cpu time when a wake lock is acquired if the screen is off.
2805                // If the screen is on, we don't distribute the power amongst partial wakelocks.
2806                if (DEBUG_ENERGY_CPU) {
2807                    Slog.d(TAG, "Updating cpu time because of +wake_lock");
2808                }
2809                requestWakelockCpuUpdate();
2810            }
2811            getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
2812        }
2813    }
2814
2815    public void noteStopWakeLocked(int uid, int pid, String name, String historyName, int type,
2816            long elapsedRealtime, long uptime) {
2817        uid = mapUid(uid);
2818        if (type == WAKE_TYPE_PARTIAL) {
2819            mWakeLockNesting--;
2820            if (mRecordAllHistory) {
2821                if (historyName == null) {
2822                    historyName = name;
2823                }
2824                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
2825                        uid, 0)) {
2826                    addHistoryEventLocked(elapsedRealtime, uptime,
2827                            HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
2828                }
2829            }
2830            if (mWakeLockNesting == 0) {
2831                mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
2832                if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
2833                        + Integer.toHexString(mHistoryCur.states));
2834                mInitialAcquireWakeName = null;
2835                mInitialAcquireWakeUid = -1;
2836                addHistoryRecordLocked(elapsedRealtime, uptime);
2837            }
2838        }
2839        if (uid >= 0) {
2840            if (mOnBatteryScreenOffTimeBase.isRunning()) {
2841                if (DEBUG_ENERGY_CPU) {
2842                    Slog.d(TAG, "Updating cpu time because of -wake_lock");
2843                }
2844                requestWakelockCpuUpdate();
2845            }
2846            getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
2847        }
2848    }
2849
2850    public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
2851            String historyName, int type, boolean unimportantForLogging) {
2852        final long elapsedRealtime = SystemClock.elapsedRealtime();
2853        final long uptime = SystemClock.uptimeMillis();
2854        final int N = ws.size();
2855        for (int i=0; i<N; i++) {
2856            noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
2857                    elapsedRealtime, uptime);
2858        }
2859    }
2860
2861    public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
2862            String historyName, int type, WorkSource newWs, int newPid, String newName,
2863            String newHistoryName, int newType, boolean newUnimportantForLogging) {
2864        final long elapsedRealtime = SystemClock.elapsedRealtime();
2865        final long uptime = SystemClock.uptimeMillis();
2866        // For correct semantics, we start the need worksources first, so that we won't
2867        // make inappropriate history items as if all wake locks went away and new ones
2868        // appeared.  This is okay because tracking of wake locks allows nesting.
2869        final int NN = newWs.size();
2870        for (int i=0; i<NN; i++) {
2871            noteStartWakeLocked(newWs.get(i), newPid, newName, newHistoryName, newType,
2872                    newUnimportantForLogging, elapsedRealtime, uptime);
2873        }
2874        final int NO = ws.size();
2875        for (int i=0; i<NO; i++) {
2876            noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
2877        }
2878    }
2879
2880    public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
2881            String historyName, int type) {
2882        final long elapsedRealtime = SystemClock.elapsedRealtime();
2883        final long uptime = SystemClock.uptimeMillis();
2884        final int N = ws.size();
2885        for (int i=0; i<N; i++) {
2886            noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
2887        }
2888    }
2889
2890    void aggregateLastWakeupUptimeLocked(long uptimeMs) {
2891        if (mLastWakeupReason != null) {
2892            long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
2893            SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
2894            timer.addCurrentReportedCount(1);
2895            timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds
2896            mLastWakeupReason = null;
2897        }
2898    }
2899
2900    public void noteWakeupReasonLocked(String reason) {
2901        final long elapsedRealtime = SystemClock.elapsedRealtime();
2902        final long uptime = SystemClock.uptimeMillis();
2903        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
2904                + Integer.toHexString(mHistoryCur.states));
2905        aggregateLastWakeupUptimeLocked(uptime);
2906        mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
2907        mHistoryCur.wakeReasonTag.string = reason;
2908        mHistoryCur.wakeReasonTag.uid = 0;
2909        mLastWakeupReason = reason;
2910        mLastWakeupUptimeMs = uptime;
2911        addHistoryRecordLocked(elapsedRealtime, uptime);
2912    }
2913
2914    public boolean startAddingCpuLocked() {
2915        mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
2916        return mOnBatteryInternal;
2917    }
2918
2919    public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
2920                                      int statSystemTime, int statIOWaitTime, int statIrqTime,
2921                                      int statSoftIrqTime, int statIdleTime) {
2922        if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
2923                + " user=" + statUserTime + " sys=" + statSystemTime
2924                + " io=" + statIOWaitTime + " irq=" + statIrqTime
2925                + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
2926        mCurStepCpuUserTime += totalUTime;
2927        mCurStepCpuSystemTime += totalSTime;
2928        mCurStepStatUserTime += statUserTime;
2929        mCurStepStatSystemTime += statSystemTime;
2930        mCurStepStatIOWaitTime += statIOWaitTime;
2931        mCurStepStatIrqTime += statIrqTime;
2932        mCurStepStatSoftIrqTime += statSoftIrqTime;
2933        mCurStepStatIdleTime += statIdleTime;
2934    }
2935
2936    public void noteProcessDiedLocked(int uid, int pid) {
2937        uid = mapUid(uid);
2938        Uid u = mUidStats.get(uid);
2939        if (u != null) {
2940            u.mPids.remove(pid);
2941        }
2942    }
2943
2944    public long getProcessWakeTime(int uid, int pid, long realtime) {
2945        uid = mapUid(uid);
2946        Uid u = mUidStats.get(uid);
2947        if (u != null) {
2948            Uid.Pid p = u.mPids.get(pid);
2949            if (p != null) {
2950                return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
2951            }
2952        }
2953        return 0;
2954    }
2955
2956    public void reportExcessiveWakeLocked(int uid, String proc, long overTime, long usedTime) {
2957        uid = mapUid(uid);
2958        Uid u = mUidStats.get(uid);
2959        if (u != null) {
2960            u.reportExcessiveWakeLocked(proc, overTime, usedTime);
2961        }
2962    }
2963
2964    public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
2965        uid = mapUid(uid);
2966        Uid u = mUidStats.get(uid);
2967        if (u != null) {
2968            u.reportExcessiveCpuLocked(proc, overTime, usedTime);
2969        }
2970    }
2971
2972    int mSensorNesting;
2973
2974    public void noteStartSensorLocked(int uid, int sensor) {
2975        uid = mapUid(uid);
2976        final long elapsedRealtime = SystemClock.elapsedRealtime();
2977        final long uptime = SystemClock.uptimeMillis();
2978        if (mSensorNesting == 0) {
2979            mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
2980            if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
2981                    + Integer.toHexString(mHistoryCur.states));
2982            addHistoryRecordLocked(elapsedRealtime, uptime);
2983        }
2984        mSensorNesting++;
2985        getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime);
2986    }
2987
2988    public void noteStopSensorLocked(int uid, int sensor) {
2989        uid = mapUid(uid);
2990        final long elapsedRealtime = SystemClock.elapsedRealtime();
2991        final long uptime = SystemClock.uptimeMillis();
2992        mSensorNesting--;
2993        if (mSensorNesting == 0) {
2994            mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
2995            if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
2996                    + Integer.toHexString(mHistoryCur.states));
2997            addHistoryRecordLocked(elapsedRealtime, uptime);
2998        }
2999        getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime);
3000    }
3001
3002    int mGpsNesting;
3003
3004    public void noteStartGpsLocked(int uid) {
3005        uid = mapUid(uid);
3006        final long elapsedRealtime = SystemClock.elapsedRealtime();
3007        final long uptime = SystemClock.uptimeMillis();
3008        if (mGpsNesting == 0) {
3009            mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
3010            if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
3011                    + Integer.toHexString(mHistoryCur.states));
3012            addHistoryRecordLocked(elapsedRealtime, uptime);
3013        }
3014        mGpsNesting++;
3015        getUidStatsLocked(uid).noteStartGps(elapsedRealtime);
3016    }
3017
3018    public void noteStopGpsLocked(int uid) {
3019        uid = mapUid(uid);
3020        final long elapsedRealtime = SystemClock.elapsedRealtime();
3021        final long uptime = SystemClock.uptimeMillis();
3022        mGpsNesting--;
3023        if (mGpsNesting == 0) {
3024            mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
3025            if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
3026                    + Integer.toHexString(mHistoryCur.states));
3027            addHistoryRecordLocked(elapsedRealtime, uptime);
3028        }
3029        getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
3030    }
3031
3032    public void noteScreenStateLocked(int state) {
3033        if (mScreenState != state) {
3034            recordDailyStatsIfNeededLocked(true);
3035            final int oldState = mScreenState;
3036            mScreenState = state;
3037            if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
3038                    + ", newState=" + Display.stateToString(state));
3039
3040            if (state != Display.STATE_UNKNOWN) {
3041                int stepState = state-1;
3042                if (stepState < 4) {
3043                    mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
3044                    mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
3045                } else {
3046                    Slog.wtf(TAG, "Unexpected screen state: " + state);
3047                }
3048            }
3049
3050            if (state == Display.STATE_ON) {
3051                // Screen turning on.
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 on to: "
3056                        + Integer.toHexString(mHistoryCur.states));
3057                addHistoryRecordLocked(elapsedRealtime, uptime);
3058                mScreenOnTimer.startRunningLocked(elapsedRealtime);
3059                if (mScreenBrightnessBin >= 0) {
3060                    mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
3061                }
3062
3063                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
3064                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
3065
3066                // Fake a wake lock, so we consider the device waked as long
3067                // as the screen is on.
3068                noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
3069                        elapsedRealtime, uptime);
3070
3071                // Update discharge amounts.
3072                if (mOnBatteryInternal) {
3073                    updateDischargeScreenLevelsLocked(false, true);
3074                }
3075            } else if (oldState == Display.STATE_ON) {
3076                // Screen turning off or dozing.
3077                final long elapsedRealtime = SystemClock.elapsedRealtime();
3078                final long uptime = SystemClock.uptimeMillis();
3079                mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
3080                if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
3081                        + Integer.toHexString(mHistoryCur.states));
3082                addHistoryRecordLocked(elapsedRealtime, uptime);
3083                mScreenOnTimer.stopRunningLocked(elapsedRealtime);
3084                if (mScreenBrightnessBin >= 0) {
3085                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
3086                }
3087
3088                noteStopWakeLocked(-1, -1, "screen", "screen", WAKE_TYPE_PARTIAL,
3089                        elapsedRealtime, uptime);
3090
3091                updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
3092                        SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
3093
3094                // Update discharge amounts.
3095                if (mOnBatteryInternal) {
3096                    updateDischargeScreenLevelsLocked(true, false);
3097                }
3098            }
3099        }
3100    }
3101
3102    public void noteScreenBrightnessLocked(int brightness) {
3103        // Bin the brightness.
3104        int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
3105        if (bin < 0) bin = 0;
3106        else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
3107        if (mScreenBrightnessBin != bin) {
3108            final long elapsedRealtime = SystemClock.elapsedRealtime();
3109            final long uptime = SystemClock.uptimeMillis();
3110            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
3111                    | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
3112            if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
3113                    + Integer.toHexString(mHistoryCur.states));
3114            addHistoryRecordLocked(elapsedRealtime, uptime);
3115            if (mScreenState == Display.STATE_ON) {
3116                if (mScreenBrightnessBin >= 0) {
3117                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
3118                }
3119                mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
3120            }
3121            mScreenBrightnessBin = bin;
3122        }
3123    }
3124
3125    public void noteUserActivityLocked(int uid, int event) {
3126        if (mOnBatteryInternal) {
3127            uid = mapUid(uid);
3128            getUidStatsLocked(uid).noteUserActivityLocked(event);
3129        }
3130    }
3131
3132    public void noteWakeUpLocked(String reason, int reasonUid) {
3133        final long elapsedRealtime = SystemClock.elapsedRealtime();
3134        final long uptime = SystemClock.uptimeMillis();
3135        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
3136                reason, reasonUid);
3137    }
3138
3139    public void noteInteractiveLocked(boolean interactive) {
3140        if (mInteractive != interactive) {
3141            final long elapsedRealtime = SystemClock.elapsedRealtime();
3142            mInteractive = interactive;
3143            if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
3144            if (interactive) {
3145                mInteractiveTimer.startRunningLocked(elapsedRealtime);
3146            } else {
3147                mInteractiveTimer.stopRunningLocked(elapsedRealtime);
3148            }
3149        }
3150    }
3151
3152    public void noteConnectivityChangedLocked(int type, String extra) {
3153        final long elapsedRealtime = SystemClock.elapsedRealtime();
3154        final long uptime = SystemClock.uptimeMillis();
3155        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
3156                extra, type);
3157        mNumConnectivityChange++;
3158    }
3159
3160    public void noteMobileRadioPowerState(int powerState, long timestampNs) {
3161        final long elapsedRealtime = SystemClock.elapsedRealtime();
3162        final long uptime = SystemClock.uptimeMillis();
3163        if (mMobileRadioPowerState != powerState) {
3164            long realElapsedRealtimeMs;
3165            final boolean active =
3166                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
3167                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
3168            if (active) {
3169                mMobileRadioActiveStartTime = realElapsedRealtimeMs = elapsedRealtime;
3170                mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
3171            } else {
3172                realElapsedRealtimeMs = timestampNs / (1000*1000);
3173                long lastUpdateTimeMs = mMobileRadioActiveStartTime;
3174                if (realElapsedRealtimeMs < lastUpdateTimeMs) {
3175                    Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
3176                            + " is before start time " + lastUpdateTimeMs);
3177                    realElapsedRealtimeMs = elapsedRealtime;
3178                } else if (realElapsedRealtimeMs < elapsedRealtime) {
3179                    mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
3180                            - realElapsedRealtimeMs);
3181                }
3182                mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
3183            }
3184            if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
3185                    + Integer.toHexString(mHistoryCur.states));
3186            addHistoryRecordLocked(elapsedRealtime, uptime);
3187            mMobileRadioPowerState = powerState;
3188            if (active) {
3189                mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
3190                mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
3191            } else {
3192                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
3193                updateMobileRadioStateLocked(realElapsedRealtimeMs);
3194                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
3195            }
3196        }
3197    }
3198
3199    public void notePowerSaveMode(boolean enabled) {
3200        if (mPowerSaveModeEnabled != enabled) {
3201            int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
3202            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
3203            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
3204            final long elapsedRealtime = SystemClock.elapsedRealtime();
3205            final long uptime = SystemClock.uptimeMillis();
3206            mPowerSaveModeEnabled = enabled;
3207            if (enabled) {
3208                mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
3209                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
3210                        + Integer.toHexString(mHistoryCur.states2));
3211                mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime);
3212            } else {
3213                mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
3214                if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
3215                        + Integer.toHexString(mHistoryCur.states2));
3216                mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime);
3217            }
3218            addHistoryRecordLocked(elapsedRealtime, uptime);
3219        }
3220    }
3221
3222    public void noteDeviceIdleModeLocked(boolean enabled, String activeReason, int activeUid) {
3223        final long elapsedRealtime = SystemClock.elapsedRealtime();
3224        final long uptime = SystemClock.uptimeMillis();
3225        boolean nowIdling = enabled;
3226        if (mDeviceIdling && !enabled && activeReason == null) {
3227            // We don't go out of general idling mode until explicitly taken out of
3228            // device idle through going active or significant motion.
3229            nowIdling = true;
3230        }
3231        if (mDeviceIdling != nowIdling) {
3232            mDeviceIdling = nowIdling;
3233            int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
3234            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
3235            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
3236            if (enabled) {
3237                mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
3238            } else {
3239                mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
3240            }
3241        }
3242        if (mDeviceIdleModeEnabled != enabled) {
3243            mDeviceIdleModeEnabled = enabled;
3244            addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
3245                    activeReason != null ? activeReason : "", activeUid);
3246            if (enabled) {
3247                mHistoryCur.states2 |= HistoryItem.STATE2_DEVICE_IDLE_FLAG;
3248                if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode enabled to: "
3249                        + Integer.toHexString(mHistoryCur.states2));
3250                mDeviceIdleModeEnabledTimer.startRunningLocked(elapsedRealtime);
3251            } else {
3252                mHistoryCur.states2 &= ~HistoryItem.STATE2_DEVICE_IDLE_FLAG;
3253                if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode disabled to: "
3254                        + Integer.toHexString(mHistoryCur.states2));
3255                mDeviceIdleModeEnabledTimer.stopRunningLocked(elapsedRealtime);
3256            }
3257            addHistoryRecordLocked(elapsedRealtime, uptime);
3258        }
3259    }
3260
3261    public void notePackageInstalledLocked(String pkgName, int versionCode) {
3262        final long elapsedRealtime = SystemClock.elapsedRealtime();
3263        final long uptime = SystemClock.uptimeMillis();
3264        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
3265                pkgName, versionCode);
3266        PackageChange pc = new PackageChange();
3267        pc.mPackageName = pkgName;
3268        pc.mUpdate = true;
3269        pc.mVersionCode = versionCode;
3270        addPackageChange(pc);
3271    }
3272
3273    public void notePackageUninstalledLocked(String pkgName) {
3274        final long elapsedRealtime = SystemClock.elapsedRealtime();
3275        final long uptime = SystemClock.uptimeMillis();
3276        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
3277                pkgName, 0);
3278        PackageChange pc = new PackageChange();
3279        pc.mPackageName = pkgName;
3280        pc.mUpdate = true;
3281        addPackageChange(pc);
3282    }
3283
3284    private void addPackageChange(PackageChange pc) {
3285        if (mDailyPackageChanges == null) {
3286            mDailyPackageChanges = new ArrayList<>();
3287        }
3288        mDailyPackageChanges.add(pc);
3289    }
3290
3291    public void notePhoneOnLocked() {
3292        if (!mPhoneOn) {
3293            final long elapsedRealtime = SystemClock.elapsedRealtime();
3294            final long uptime = SystemClock.uptimeMillis();
3295            mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
3296            if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
3297                    + Integer.toHexString(mHistoryCur.states));
3298            addHistoryRecordLocked(elapsedRealtime, uptime);
3299            mPhoneOn = true;
3300            mPhoneOnTimer.startRunningLocked(elapsedRealtime);
3301        }
3302    }
3303
3304    public void notePhoneOffLocked() {
3305        if (mPhoneOn) {
3306            final long elapsedRealtime = SystemClock.elapsedRealtime();
3307            final long uptime = SystemClock.uptimeMillis();
3308            mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
3309            if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
3310                    + Integer.toHexString(mHistoryCur.states));
3311            addHistoryRecordLocked(elapsedRealtime, uptime);
3312            mPhoneOn = false;
3313            mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
3314        }
3315    }
3316
3317    void stopAllPhoneSignalStrengthTimersLocked(int except) {
3318        final long elapsedRealtime = SystemClock.elapsedRealtime();
3319        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
3320            if (i == except) {
3321                continue;
3322            }
3323            while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
3324                mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
3325            }
3326        }
3327    }
3328
3329    private int fixPhoneServiceState(int state, int signalBin) {
3330        if (mPhoneSimStateRaw == TelephonyManager.SIM_STATE_ABSENT) {
3331            // In this case we will always be STATE_OUT_OF_SERVICE, so need
3332            // to infer that we are scanning from other data.
3333            if (state == ServiceState.STATE_OUT_OF_SERVICE
3334                    && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
3335                state = ServiceState.STATE_IN_SERVICE;
3336            }
3337        }
3338
3339        return state;
3340    }
3341
3342    private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) {
3343        boolean scanning = false;
3344        boolean newHistory = false;
3345
3346        mPhoneServiceStateRaw = state;
3347        mPhoneSimStateRaw = simState;
3348        mPhoneSignalStrengthBinRaw = strengthBin;
3349
3350        final long elapsedRealtime = SystemClock.elapsedRealtime();
3351        final long uptime = SystemClock.uptimeMillis();
3352
3353        if (simState == TelephonyManager.SIM_STATE_ABSENT) {
3354            // In this case we will always be STATE_OUT_OF_SERVICE, so need
3355            // to infer that we are scanning from other data.
3356            if (state == ServiceState.STATE_OUT_OF_SERVICE
3357                    && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
3358                state = ServiceState.STATE_IN_SERVICE;
3359            }
3360        }
3361
3362        // If the phone is powered off, stop all timers.
3363        if (state == ServiceState.STATE_POWER_OFF) {
3364            strengthBin = -1;
3365
3366        // If we are in service, make sure the correct signal string timer is running.
3367        } else if (state == ServiceState.STATE_IN_SERVICE) {
3368            // Bin will be changed below.
3369
3370        // If we're out of service, we are in the lowest signal strength
3371        // bin and have the scanning bit set.
3372        } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
3373            scanning = true;
3374            strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
3375            if (!mPhoneSignalScanningTimer.isRunningLocked()) {
3376                mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
3377                newHistory = true;
3378                if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
3379                        + Integer.toHexString(mHistoryCur.states));
3380                mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
3381            }
3382        }
3383
3384        if (!scanning) {
3385            // If we are no longer scanning, then stop the scanning timer.
3386            if (mPhoneSignalScanningTimer.isRunningLocked()) {
3387                mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
3388                if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
3389                        + Integer.toHexString(mHistoryCur.states));
3390                newHistory = true;
3391                mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
3392            }
3393        }
3394
3395        if (mPhoneServiceState != state) {
3396            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
3397                    | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
3398            if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
3399                    + Integer.toHexString(mHistoryCur.states));
3400            newHistory = true;
3401            mPhoneServiceState = state;
3402        }
3403
3404        if (mPhoneSignalStrengthBin != strengthBin) {
3405            if (mPhoneSignalStrengthBin >= 0) {
3406                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
3407                        elapsedRealtime);
3408            }
3409            if (strengthBin >= 0) {
3410                if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
3411                    mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
3412                }
3413                mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
3414                        | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
3415                if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
3416                        + Integer.toHexString(mHistoryCur.states));
3417                newHistory = true;
3418            } else {
3419                stopAllPhoneSignalStrengthTimersLocked(-1);
3420            }
3421            mPhoneSignalStrengthBin = strengthBin;
3422        }
3423
3424        if (newHistory) {
3425            addHistoryRecordLocked(elapsedRealtime, uptime);
3426        }
3427    }
3428
3429    /**
3430     * Telephony stack updates the phone state.
3431     * @param state phone state from ServiceState.getState()
3432     */
3433    public void notePhoneStateLocked(int state, int simState) {
3434        updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
3435    }
3436
3437    public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
3438        // Bin the strength.
3439        int bin = signalStrength.getLevel();
3440        updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
3441    }
3442
3443    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
3444        int bin = DATA_CONNECTION_NONE;
3445        if (hasData) {
3446            switch (dataType) {
3447                case TelephonyManager.NETWORK_TYPE_EDGE:
3448                    bin = DATA_CONNECTION_EDGE;
3449                    break;
3450                case TelephonyManager.NETWORK_TYPE_GPRS:
3451                    bin = DATA_CONNECTION_GPRS;
3452                    break;
3453                case TelephonyManager.NETWORK_TYPE_UMTS:
3454                    bin = DATA_CONNECTION_UMTS;
3455                    break;
3456                case TelephonyManager.NETWORK_TYPE_CDMA:
3457                    bin = DATA_CONNECTION_CDMA;
3458                    break;
3459                case TelephonyManager.NETWORK_TYPE_EVDO_0:
3460                    bin = DATA_CONNECTION_EVDO_0;
3461                    break;
3462                case TelephonyManager.NETWORK_TYPE_EVDO_A:
3463                    bin = DATA_CONNECTION_EVDO_A;
3464                    break;
3465                case TelephonyManager.NETWORK_TYPE_1xRTT:
3466                    bin = DATA_CONNECTION_1xRTT;
3467                    break;
3468                case TelephonyManager.NETWORK_TYPE_HSDPA:
3469                    bin = DATA_CONNECTION_HSDPA;
3470                    break;
3471                case TelephonyManager.NETWORK_TYPE_HSUPA:
3472                    bin = DATA_CONNECTION_HSUPA;
3473                    break;
3474                case TelephonyManager.NETWORK_TYPE_HSPA:
3475                    bin = DATA_CONNECTION_HSPA;
3476                    break;
3477                case TelephonyManager.NETWORK_TYPE_IDEN:
3478                    bin = DATA_CONNECTION_IDEN;
3479                    break;
3480                case TelephonyManager.NETWORK_TYPE_EVDO_B:
3481                    bin = DATA_CONNECTION_EVDO_B;
3482                    break;
3483                case TelephonyManager.NETWORK_TYPE_LTE:
3484                    bin = DATA_CONNECTION_LTE;
3485                    break;
3486                case TelephonyManager.NETWORK_TYPE_EHRPD:
3487                    bin = DATA_CONNECTION_EHRPD;
3488                    break;
3489                case TelephonyManager.NETWORK_TYPE_HSPAP:
3490                    bin = DATA_CONNECTION_HSPAP;
3491                    break;
3492                default:
3493                    bin = DATA_CONNECTION_OTHER;
3494                    break;
3495            }
3496        }
3497        if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
3498        if (mPhoneDataConnectionType != bin) {
3499            final long elapsedRealtime = SystemClock.elapsedRealtime();
3500            final long uptime = SystemClock.uptimeMillis();
3501            mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
3502                    | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
3503            if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
3504                    + Integer.toHexString(mHistoryCur.states));
3505            addHistoryRecordLocked(elapsedRealtime, uptime);
3506            if (mPhoneDataConnectionType >= 0) {
3507                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
3508                        elapsedRealtime);
3509            }
3510            mPhoneDataConnectionType = bin;
3511            mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
3512        }
3513    }
3514
3515    public void noteWifiOnLocked() {
3516        if (!mWifiOn) {
3517            final long elapsedRealtime = SystemClock.elapsedRealtime();
3518            final long uptime = SystemClock.uptimeMillis();
3519            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
3520            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
3521                    + Integer.toHexString(mHistoryCur.states));
3522            addHistoryRecordLocked(elapsedRealtime, uptime);
3523            mWifiOn = true;
3524            mWifiOnTimer.startRunningLocked(elapsedRealtime);
3525            scheduleSyncExternalWifiStatsLocked("wifi-off");
3526        }
3527    }
3528
3529    public void noteWifiOffLocked() {
3530        final long elapsedRealtime = SystemClock.elapsedRealtime();
3531        final long uptime = SystemClock.uptimeMillis();
3532        if (mWifiOn) {
3533            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
3534            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
3535                    + Integer.toHexString(mHistoryCur.states));
3536            addHistoryRecordLocked(elapsedRealtime, uptime);
3537            mWifiOn = false;
3538            mWifiOnTimer.stopRunningLocked(elapsedRealtime);
3539            scheduleSyncExternalWifiStatsLocked("wifi-on");
3540        }
3541    }
3542
3543    public void noteAudioOnLocked(int uid) {
3544        uid = mapUid(uid);
3545        final long elapsedRealtime = SystemClock.elapsedRealtime();
3546        final long uptime = SystemClock.uptimeMillis();
3547        if (mAudioOnNesting == 0) {
3548            mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
3549            if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
3550                    + Integer.toHexString(mHistoryCur.states));
3551            addHistoryRecordLocked(elapsedRealtime, uptime);
3552            mAudioOnTimer.startRunningLocked(elapsedRealtime);
3553        }
3554        mAudioOnNesting++;
3555        getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
3556    }
3557
3558    public void noteAudioOffLocked(int uid) {
3559        if (mAudioOnNesting == 0) {
3560            return;
3561        }
3562        uid = mapUid(uid);
3563        final long elapsedRealtime = SystemClock.elapsedRealtime();
3564        final long uptime = SystemClock.uptimeMillis();
3565        if (--mAudioOnNesting == 0) {
3566            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
3567            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
3568                    + Integer.toHexString(mHistoryCur.states));
3569            addHistoryRecordLocked(elapsedRealtime, uptime);
3570            mAudioOnTimer.stopRunningLocked(elapsedRealtime);
3571        }
3572        getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
3573    }
3574
3575    public void noteVideoOnLocked(int uid) {
3576        uid = mapUid(uid);
3577        final long elapsedRealtime = SystemClock.elapsedRealtime();
3578        final long uptime = SystemClock.uptimeMillis();
3579        if (mVideoOnNesting == 0) {
3580            mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
3581            if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
3582                    + Integer.toHexString(mHistoryCur.states));
3583            addHistoryRecordLocked(elapsedRealtime, uptime);
3584            mVideoOnTimer.startRunningLocked(elapsedRealtime);
3585        }
3586        mVideoOnNesting++;
3587        getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
3588    }
3589
3590    public void noteVideoOffLocked(int uid) {
3591        if (mVideoOnNesting == 0) {
3592            return;
3593        }
3594        uid = mapUid(uid);
3595        final long elapsedRealtime = SystemClock.elapsedRealtime();
3596        final long uptime = SystemClock.uptimeMillis();
3597        if (--mVideoOnNesting == 0) {
3598            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
3599            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
3600                    + Integer.toHexString(mHistoryCur.states));
3601            addHistoryRecordLocked(elapsedRealtime, uptime);
3602            mVideoOnTimer.stopRunningLocked(elapsedRealtime);
3603        }
3604        getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
3605    }
3606
3607    public void noteResetAudioLocked() {
3608        if (mAudioOnNesting > 0) {
3609            final long elapsedRealtime = SystemClock.elapsedRealtime();
3610            final long uptime = SystemClock.uptimeMillis();
3611            mAudioOnNesting = 0;
3612            mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
3613            if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
3614                    + Integer.toHexString(mHistoryCur.states));
3615            addHistoryRecordLocked(elapsedRealtime, uptime);
3616            mAudioOnTimer.stopAllRunningLocked(elapsedRealtime);
3617            for (int i=0; i<mUidStats.size(); i++) {
3618                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3619                uid.noteResetAudioLocked(elapsedRealtime);
3620            }
3621        }
3622    }
3623
3624    public void noteResetVideoLocked() {
3625        if (mVideoOnNesting > 0) {
3626            final long elapsedRealtime = SystemClock.elapsedRealtime();
3627            final long uptime = SystemClock.uptimeMillis();
3628            mAudioOnNesting = 0;
3629            mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
3630            if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
3631                    + Integer.toHexString(mHistoryCur.states));
3632            addHistoryRecordLocked(elapsedRealtime, uptime);
3633            mVideoOnTimer.stopAllRunningLocked(elapsedRealtime);
3634            for (int i=0; i<mUidStats.size(); i++) {
3635                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3636                uid.noteResetVideoLocked(elapsedRealtime);
3637            }
3638        }
3639    }
3640
3641    public void noteActivityResumedLocked(int uid) {
3642        uid = mapUid(uid);
3643        getUidStatsLocked(uid).noteActivityResumedLocked(SystemClock.elapsedRealtime());
3644    }
3645
3646    public void noteActivityPausedLocked(int uid) {
3647        uid = mapUid(uid);
3648        getUidStatsLocked(uid).noteActivityPausedLocked(SystemClock.elapsedRealtime());
3649    }
3650
3651    public void noteVibratorOnLocked(int uid, long durationMillis) {
3652        uid = mapUid(uid);
3653        getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis);
3654    }
3655
3656    public void noteVibratorOffLocked(int uid) {
3657        uid = mapUid(uid);
3658        getUidStatsLocked(uid).noteVibratorOffLocked();
3659    }
3660
3661    public void noteFlashlightOnLocked(int uid) {
3662        uid = mapUid(uid);
3663        final long elapsedRealtime = SystemClock.elapsedRealtime();
3664        final long uptime = SystemClock.uptimeMillis();
3665        if (mFlashlightOnNesting++ == 0) {
3666            mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
3667            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
3668                    + Integer.toHexString(mHistoryCur.states2));
3669            addHistoryRecordLocked(elapsedRealtime, uptime);
3670            mFlashlightOnTimer.startRunningLocked(elapsedRealtime);
3671        }
3672        getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime);
3673    }
3674
3675    public void noteFlashlightOffLocked(int uid) {
3676        if (mFlashlightOnNesting == 0) {
3677            return;
3678        }
3679        uid = mapUid(uid);
3680        final long elapsedRealtime = SystemClock.elapsedRealtime();
3681        final long uptime = SystemClock.uptimeMillis();
3682        if (--mFlashlightOnNesting == 0) {
3683            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
3684            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
3685                    + Integer.toHexString(mHistoryCur.states2));
3686            addHistoryRecordLocked(elapsedRealtime, uptime);
3687            mFlashlightOnTimer.stopRunningLocked(elapsedRealtime);
3688        }
3689        getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime);
3690    }
3691
3692    public void noteCameraOnLocked(int uid) {
3693        uid = mapUid(uid);
3694        final long elapsedRealtime = SystemClock.elapsedRealtime();
3695        final long uptime = SystemClock.uptimeMillis();
3696        if (mCameraOnNesting++ == 0) {
3697            mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
3698            if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
3699                    + Integer.toHexString(mHistoryCur.states2));
3700            addHistoryRecordLocked(elapsedRealtime, uptime);
3701            mCameraOnTimer.startRunningLocked(elapsedRealtime);
3702        }
3703        getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime);
3704    }
3705
3706    public void noteCameraOffLocked(int uid) {
3707        if (mCameraOnNesting == 0) {
3708            return;
3709        }
3710        uid = mapUid(uid);
3711        final long elapsedRealtime = SystemClock.elapsedRealtime();
3712        final long uptime = SystemClock.uptimeMillis();
3713        if (--mCameraOnNesting == 0) {
3714            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
3715            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
3716                    + Integer.toHexString(mHistoryCur.states2));
3717            addHistoryRecordLocked(elapsedRealtime, uptime);
3718            mCameraOnTimer.stopRunningLocked(elapsedRealtime);
3719        }
3720        getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime);
3721    }
3722
3723    public void noteResetCameraLocked() {
3724        if (mCameraOnNesting > 0) {
3725            final long elapsedRealtime = SystemClock.elapsedRealtime();
3726            final long uptime = SystemClock.uptimeMillis();
3727            mCameraOnNesting = 0;
3728            mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
3729            if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
3730                    + Integer.toHexString(mHistoryCur.states2));
3731            addHistoryRecordLocked(elapsedRealtime, uptime);
3732            mCameraOnTimer.stopAllRunningLocked(elapsedRealtime);
3733            for (int i=0; i<mUidStats.size(); i++) {
3734                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3735                uid.noteResetCameraLocked(elapsedRealtime);
3736            }
3737        }
3738    }
3739
3740    public void noteResetFlashlightLocked() {
3741        if (mFlashlightOnNesting > 0) {
3742            final long elapsedRealtime = SystemClock.elapsedRealtime();
3743            final long uptime = SystemClock.uptimeMillis();
3744            mFlashlightOnNesting = 0;
3745            mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
3746            if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
3747                    + Integer.toHexString(mHistoryCur.states2));
3748            addHistoryRecordLocked(elapsedRealtime, uptime);
3749            mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime);
3750            for (int i=0; i<mUidStats.size(); i++) {
3751                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
3752                uid.noteResetFlashlightLocked(elapsedRealtime);
3753            }
3754        }
3755    }
3756
3757    public void noteWifiRadioPowerState(int powerState, long timestampNs) {
3758        final long elapsedRealtime = SystemClock.elapsedRealtime();
3759        final long uptime = SystemClock.uptimeMillis();
3760        if (mWifiRadioPowerState != powerState) {
3761            final boolean active =
3762                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
3763                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
3764            if (active) {
3765                mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
3766            } else {
3767                mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
3768            }
3769            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
3770                    + Integer.toHexString(mHistoryCur.states));
3771            addHistoryRecordLocked(elapsedRealtime, uptime);
3772            mWifiRadioPowerState = powerState;
3773        }
3774    }
3775
3776    public void noteWifiRunningLocked(WorkSource ws) {
3777        if (!mGlobalWifiRunning) {
3778            final long elapsedRealtime = SystemClock.elapsedRealtime();
3779            final long uptime = SystemClock.uptimeMillis();
3780            mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
3781            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
3782                    + Integer.toHexString(mHistoryCur.states));
3783            addHistoryRecordLocked(elapsedRealtime, uptime);
3784            mGlobalWifiRunning = true;
3785            mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
3786            int N = ws.size();
3787            for (int i=0; i<N; i++) {
3788                int uid = mapUid(ws.get(i));
3789                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
3790            }
3791            scheduleSyncExternalWifiStatsLocked("wifi-running");
3792        } else {
3793            Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
3794        }
3795    }
3796
3797    public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
3798        if (mGlobalWifiRunning) {
3799            final long elapsedRealtime = SystemClock.elapsedRealtime();
3800            int N = oldWs.size();
3801            for (int i=0; i<N; i++) {
3802                int uid = mapUid(oldWs.get(i));
3803                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
3804            }
3805            N = newWs.size();
3806            for (int i=0; i<N; i++) {
3807                int uid = mapUid(newWs.get(i));
3808                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
3809            }
3810        } else {
3811            Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
3812        }
3813    }
3814
3815    public void noteWifiStoppedLocked(WorkSource ws) {
3816        if (mGlobalWifiRunning) {
3817            final long elapsedRealtime = SystemClock.elapsedRealtime();
3818            final long uptime = SystemClock.uptimeMillis();
3819            mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
3820            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
3821                    + Integer.toHexString(mHistoryCur.states));
3822            addHistoryRecordLocked(elapsedRealtime, uptime);
3823            mGlobalWifiRunning = false;
3824            mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
3825            int N = ws.size();
3826            for (int i=0; i<N; i++) {
3827                int uid = mapUid(ws.get(i));
3828                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
3829            }
3830            scheduleSyncExternalWifiStatsLocked("wifi-stopped");
3831        } else {
3832            Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
3833        }
3834    }
3835
3836    public void noteWifiStateLocked(int wifiState, String accessPoint) {
3837        if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
3838        if (mWifiState != wifiState) {
3839            final long elapsedRealtime = SystemClock.elapsedRealtime();
3840            if (mWifiState >= 0) {
3841                mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
3842            }
3843            mWifiState = wifiState;
3844            mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
3845            scheduleSyncExternalWifiStatsLocked("wifi-state");
3846        }
3847    }
3848
3849    public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
3850        if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
3851        if (mWifiSupplState != supplState) {
3852            final long elapsedRealtime = SystemClock.elapsedRealtime();
3853            final long uptime = SystemClock.uptimeMillis();
3854            if (mWifiSupplState >= 0) {
3855                mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
3856            }
3857            mWifiSupplState = supplState;
3858            mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime);
3859            mHistoryCur.states2 =
3860                    (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
3861                    | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
3862            if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
3863                    + Integer.toHexString(mHistoryCur.states2));
3864            addHistoryRecordLocked(elapsedRealtime, uptime);
3865        }
3866    }
3867
3868    void stopAllWifiSignalStrengthTimersLocked(int except) {
3869        final long elapsedRealtime = SystemClock.elapsedRealtime();
3870        for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
3871            if (i == except) {
3872                continue;
3873            }
3874            while (mWifiSignalStrengthsTimer[i].isRunningLocked()) {
3875                mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
3876            }
3877        }
3878    }
3879
3880    public void noteWifiRssiChangedLocked(int newRssi) {
3881        int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
3882        if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
3883        if (mWifiSignalStrengthBin != strengthBin) {
3884            final long elapsedRealtime = SystemClock.elapsedRealtime();
3885            final long uptime = SystemClock.uptimeMillis();
3886            if (mWifiSignalStrengthBin >= 0) {
3887                mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
3888                        elapsedRealtime);
3889            }
3890            if (strengthBin >= 0) {
3891                if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
3892                    mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
3893                }
3894                mHistoryCur.states2 =
3895                        (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
3896                        | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
3897                if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
3898                        + Integer.toHexString(mHistoryCur.states2));
3899                addHistoryRecordLocked(elapsedRealtime, uptime);
3900            } else {
3901                stopAllWifiSignalStrengthTimersLocked(-1);
3902            }
3903            mWifiSignalStrengthBin = strengthBin;
3904        }
3905    }
3906
3907    int mWifiFullLockNesting = 0;
3908
3909    public void noteFullWifiLockAcquiredLocked(int uid) {
3910        uid = mapUid(uid);
3911        final long elapsedRealtime = SystemClock.elapsedRealtime();
3912        final long uptime = SystemClock.uptimeMillis();
3913        if (mWifiFullLockNesting == 0) {
3914            mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
3915            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
3916                    + Integer.toHexString(mHistoryCur.states));
3917            addHistoryRecordLocked(elapsedRealtime, uptime);
3918        }
3919        mWifiFullLockNesting++;
3920        getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
3921    }
3922
3923    public void noteFullWifiLockReleasedLocked(int uid) {
3924        uid = mapUid(uid);
3925        final long elapsedRealtime = SystemClock.elapsedRealtime();
3926        final long uptime = SystemClock.uptimeMillis();
3927        mWifiFullLockNesting--;
3928        if (mWifiFullLockNesting == 0) {
3929            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
3930            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
3931                    + Integer.toHexString(mHistoryCur.states));
3932            addHistoryRecordLocked(elapsedRealtime, uptime);
3933        }
3934        getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
3935    }
3936
3937    int mWifiScanNesting = 0;
3938
3939    public void noteWifiScanStartedLocked(int uid) {
3940        uid = mapUid(uid);
3941        final long elapsedRealtime = SystemClock.elapsedRealtime();
3942        final long uptime = SystemClock.uptimeMillis();
3943        if (mWifiScanNesting == 0) {
3944            mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
3945            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
3946                    + Integer.toHexString(mHistoryCur.states));
3947            addHistoryRecordLocked(elapsedRealtime, uptime);
3948        }
3949        mWifiScanNesting++;
3950        getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime);
3951    }
3952
3953    public void noteWifiScanStoppedLocked(int uid) {
3954        uid = mapUid(uid);
3955        final long elapsedRealtime = SystemClock.elapsedRealtime();
3956        final long uptime = SystemClock.uptimeMillis();
3957        mWifiScanNesting--;
3958        if (mWifiScanNesting == 0) {
3959            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
3960            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
3961                    + Integer.toHexString(mHistoryCur.states));
3962            addHistoryRecordLocked(elapsedRealtime, uptime);
3963        }
3964        getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime);
3965    }
3966
3967    public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
3968        uid = mapUid(uid);
3969        final long elapsedRealtime = SystemClock.elapsedRealtime();
3970        getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
3971    }
3972
3973    public void noteWifiBatchedScanStoppedLocked(int uid) {
3974        uid = mapUid(uid);
3975        final long elapsedRealtime = SystemClock.elapsedRealtime();
3976        getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
3977    }
3978
3979    int mWifiMulticastNesting = 0;
3980
3981    public void noteWifiMulticastEnabledLocked(int uid) {
3982        uid = mapUid(uid);
3983        final long elapsedRealtime = SystemClock.elapsedRealtime();
3984        final long uptime = SystemClock.uptimeMillis();
3985        if (mWifiMulticastNesting == 0) {
3986            mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
3987            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
3988                    + Integer.toHexString(mHistoryCur.states));
3989            addHistoryRecordLocked(elapsedRealtime, uptime);
3990        }
3991        mWifiMulticastNesting++;
3992        getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
3993    }
3994
3995    public void noteWifiMulticastDisabledLocked(int uid) {
3996        uid = mapUid(uid);
3997        final long elapsedRealtime = SystemClock.elapsedRealtime();
3998        final long uptime = SystemClock.uptimeMillis();
3999        mWifiMulticastNesting--;
4000        if (mWifiMulticastNesting == 0) {
4001            mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
4002            if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
4003                    + Integer.toHexString(mHistoryCur.states));
4004            addHistoryRecordLocked(elapsedRealtime, uptime);
4005        }
4006        getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
4007    }
4008
4009    public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
4010        int N = ws.size();
4011        for (int i=0; i<N; i++) {
4012            noteFullWifiLockAcquiredLocked(ws.get(i));
4013        }
4014    }
4015
4016    public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
4017        int N = ws.size();
4018        for (int i=0; i<N; i++) {
4019            noteFullWifiLockReleasedLocked(ws.get(i));
4020        }
4021    }
4022
4023    public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
4024        int N = ws.size();
4025        for (int i=0; i<N; i++) {
4026            noteWifiScanStartedLocked(ws.get(i));
4027        }
4028    }
4029
4030    public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
4031        int N = ws.size();
4032        for (int i=0; i<N; i++) {
4033            noteWifiScanStoppedLocked(ws.get(i));
4034        }
4035    }
4036
4037    public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
4038        int N = ws.size();
4039        for (int i=0; i<N; i++) {
4040            noteWifiBatchedScanStartedLocked(ws.get(i), csph);
4041        }
4042    }
4043
4044    public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
4045        int N = ws.size();
4046        for (int i=0; i<N; i++) {
4047            noteWifiBatchedScanStoppedLocked(ws.get(i));
4048        }
4049    }
4050
4051    public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
4052        int N = ws.size();
4053        for (int i=0; i<N; i++) {
4054            noteWifiMulticastEnabledLocked(ws.get(i));
4055        }
4056    }
4057
4058    public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
4059        int N = ws.size();
4060        for (int i=0; i<N; i++) {
4061            noteWifiMulticastDisabledLocked(ws.get(i));
4062        }
4063    }
4064
4065    private static String[] includeInStringArray(String[] array, String str) {
4066        if (ArrayUtils.indexOf(array, str) >= 0) {
4067            return array;
4068        }
4069        String[] newArray = new String[array.length+1];
4070        System.arraycopy(array, 0, newArray, 0, array.length);
4071        newArray[array.length] = str;
4072        return newArray;
4073    }
4074
4075    private static String[] excludeFromStringArray(String[] array, String str) {
4076        int index = ArrayUtils.indexOf(array, str);
4077        if (index >= 0) {
4078            String[] newArray = new String[array.length-1];
4079            if (index > 0) {
4080                System.arraycopy(array, 0, newArray, 0, index);
4081            }
4082            if (index < array.length-1) {
4083                System.arraycopy(array, index+1, newArray, index, array.length-index-1);
4084            }
4085            return newArray;
4086        }
4087        return array;
4088    }
4089
4090    public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
4091        if (TextUtils.isEmpty(iface)) return;
4092        if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
4093            mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
4094            if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
4095        } else {
4096            mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
4097            if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
4098        }
4099        if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
4100            mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
4101            if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
4102        } else {
4103            mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
4104            if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
4105        }
4106    }
4107
4108    public void noteNetworkStatsEnabledLocked() {
4109        // During device boot, qtaguid isn't enabled until after the inital
4110        // loading of battery stats. Now that they're enabled, take our initial
4111        // snapshot for future delta calculation.
4112        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
4113        updateMobileRadioStateLocked(elapsedRealtimeMs);
4114        updateWifiStateLocked(null);
4115    }
4116
4117    @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
4118        return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4119    }
4120
4121    @Override public int getScreenOnCount(int which) {
4122        return mScreenOnTimer.getCountLocked(which);
4123    }
4124
4125    @Override public long getScreenBrightnessTime(int brightnessBin,
4126            long elapsedRealtimeUs, int which) {
4127        return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
4128                elapsedRealtimeUs, which);
4129    }
4130
4131    @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
4132        return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4133    }
4134
4135    @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) {
4136        return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4137    }
4138
4139    @Override public int getPowerSaveModeEnabledCount(int which) {
4140        return mPowerSaveModeEnabledTimer.getCountLocked(which);
4141    }
4142
4143    @Override public long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which) {
4144        return mDeviceIdleModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4145    }
4146
4147    @Override public int getDeviceIdleModeEnabledCount(int which) {
4148        return mDeviceIdleModeEnabledTimer.getCountLocked(which);
4149    }
4150
4151    @Override public long getDeviceIdlingTime(long elapsedRealtimeUs, int which) {
4152        return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4153    }
4154
4155    @Override public int getDeviceIdlingCount(int which) {
4156        return mDeviceIdlingTimer.getCountLocked(which);
4157    }
4158
4159    @Override public int getNumConnectivityChange(int which) {
4160        int val = mNumConnectivityChange;
4161        if (which == STATS_CURRENT) {
4162            val -= mLoadedNumConnectivityChange;
4163        } else if (which == STATS_SINCE_UNPLUGGED) {
4164            val -= mUnpluggedNumConnectivityChange;
4165        }
4166        return val;
4167    }
4168
4169    @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
4170        return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4171    }
4172
4173    @Override public int getPhoneOnCount(int which) {
4174        return mPhoneOnTimer.getCountLocked(which);
4175    }
4176
4177    @Override public long getPhoneSignalStrengthTime(int strengthBin,
4178            long elapsedRealtimeUs, int which) {
4179        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
4180                elapsedRealtimeUs, which);
4181    }
4182
4183    @Override public long getPhoneSignalScanningTime(
4184            long elapsedRealtimeUs, int which) {
4185        return mPhoneSignalScanningTimer.getTotalTimeLocked(
4186                elapsedRealtimeUs, which);
4187    }
4188
4189    @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
4190        return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
4191    }
4192
4193    @Override public long getPhoneDataConnectionTime(int dataType,
4194            long elapsedRealtimeUs, int which) {
4195        return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
4196                elapsedRealtimeUs, which);
4197    }
4198
4199    @Override public int getPhoneDataConnectionCount(int dataType, int which) {
4200        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
4201    }
4202
4203    @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
4204        return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4205    }
4206
4207    @Override public int getMobileRadioActiveCount(int which) {
4208        return mMobileRadioActiveTimer.getCountLocked(which);
4209    }
4210
4211    @Override public long getMobileRadioActiveAdjustedTime(int which) {
4212        return mMobileRadioActiveAdjustedTime.getCountLocked(which);
4213    }
4214
4215    @Override public long getMobileRadioActiveUnknownTime(int which) {
4216        return mMobileRadioActiveUnknownTime.getCountLocked(which);
4217    }
4218
4219    @Override public int getMobileRadioActiveUnknownCount(int which) {
4220        return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
4221    }
4222
4223    @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
4224        return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4225    }
4226
4227    @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
4228        return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4229    }
4230
4231    @Override public long getWifiStateTime(int wifiState,
4232            long elapsedRealtimeUs, int which) {
4233        return mWifiStateTimer[wifiState].getTotalTimeLocked(
4234                elapsedRealtimeUs, which);
4235    }
4236
4237    @Override public int getWifiStateCount(int wifiState, int which) {
4238        return mWifiStateTimer[wifiState].getCountLocked(which);
4239    }
4240
4241    @Override public long getWifiSupplStateTime(int state,
4242            long elapsedRealtimeUs, int which) {
4243        return mWifiSupplStateTimer[state].getTotalTimeLocked(
4244                elapsedRealtimeUs, which);
4245    }
4246
4247    @Override public int getWifiSupplStateCount(int state, int which) {
4248        return mWifiSupplStateTimer[state].getCountLocked(which);
4249    }
4250
4251    @Override public long getWifiSignalStrengthTime(int strengthBin,
4252            long elapsedRealtimeUs, int which) {
4253        return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
4254                elapsedRealtimeUs, which);
4255    }
4256
4257    @Override public int getWifiSignalStrengthCount(int strengthBin, int which) {
4258        return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
4259    }
4260
4261    @Override public boolean hasBluetoothActivityReporting() {
4262        return mHasBluetoothEnergyReporting;
4263    }
4264
4265    @Override public long getBluetoothControllerActivity(int type, int which) {
4266        if (type >= 0 && type < mBluetoothActivityCounters.length) {
4267            return mBluetoothActivityCounters[type].getCountLocked(which);
4268        }
4269        return 0;
4270    }
4271
4272    @Override public boolean hasWifiActivityReporting() {
4273        return mHasWifiEnergyReporting;
4274    }
4275
4276    @Override public long getWifiControllerActivity(int type, int which) {
4277        if (type >= 0 && type < mWifiActivityCounters.length) {
4278            return mWifiActivityCounters[type].getCountLocked(which);
4279        }
4280        return 0;
4281    }
4282
4283    @Override
4284    public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
4285        return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4286    }
4287
4288    @Override
4289    public long getFlashlightOnCount(int which) {
4290        return mFlashlightOnTimer.getCountLocked(which);
4291    }
4292
4293    @Override
4294    public long getCameraOnTime(long elapsedRealtimeUs, int which) {
4295        return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4296    }
4297
4298    @Override
4299    public long getNetworkActivityBytes(int type, int which) {
4300        if (type >= 0 && type < mNetworkByteActivityCounters.length) {
4301            return mNetworkByteActivityCounters[type].getCountLocked(which);
4302        } else {
4303            return 0;
4304        }
4305    }
4306
4307    @Override
4308    public long getNetworkActivityPackets(int type, int which) {
4309        if (type >= 0 && type < mNetworkPacketActivityCounters.length) {
4310            return mNetworkPacketActivityCounters[type].getCountLocked(which);
4311        } else {
4312            return 0;
4313        }
4314    }
4315
4316    @Override public long getStartClockTime() {
4317        final long currentTime = System.currentTimeMillis();
4318        if (ensureStartClockTime(currentTime)) {
4319            recordCurrentTimeChangeLocked(currentTime, SystemClock.elapsedRealtime(),
4320                    SystemClock.uptimeMillis());
4321        }
4322        return mStartClockTime;
4323    }
4324
4325    @Override public String getStartPlatformVersion() {
4326        return mStartPlatformVersion;
4327    }
4328
4329    @Override public String getEndPlatformVersion() {
4330        return mEndPlatformVersion;
4331    }
4332
4333    @Override public int getParcelVersion() {
4334        return VERSION;
4335    }
4336
4337    @Override public boolean getIsOnBattery() {
4338        return mOnBattery;
4339    }
4340
4341    @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
4342        return mUidStats;
4343    }
4344
4345    /**
4346     * The statistics associated with a particular uid.
4347     */
4348    public final class Uid extends BatteryStats.Uid {
4349
4350        final int mUid;
4351
4352        boolean mWifiRunning;
4353        StopwatchTimer mWifiRunningTimer;
4354
4355        boolean mFullWifiLockOut;
4356        StopwatchTimer mFullWifiLockTimer;
4357
4358        boolean mWifiScanStarted;
4359        StopwatchTimer mWifiScanTimer;
4360
4361        static final int NO_BATCHED_SCAN_STARTED = -1;
4362        int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
4363        StopwatchTimer[] mWifiBatchedScanTimer;
4364
4365        boolean mWifiMulticastEnabled;
4366        StopwatchTimer mWifiMulticastTimer;
4367
4368        StopwatchTimer mAudioTurnedOnTimer;
4369        StopwatchTimer mVideoTurnedOnTimer;
4370        StopwatchTimer mFlashlightTurnedOnTimer;
4371        StopwatchTimer mCameraTurnedOnTimer;
4372
4373
4374        StopwatchTimer mForegroundActivityTimer;
4375
4376        static final int PROCESS_STATE_NONE = NUM_PROCESS_STATE;
4377        int mProcessState = PROCESS_STATE_NONE;
4378        StopwatchTimer[] mProcessStateTimer;
4379
4380        BatchTimer mVibratorOnTimer;
4381
4382        Counter[] mUserActivityCounters;
4383
4384        LongSamplingCounter[] mNetworkByteActivityCounters;
4385        LongSamplingCounter[] mNetworkPacketActivityCounters;
4386        LongSamplingCounter mMobileRadioActiveTime;
4387        LongSamplingCounter mMobileRadioActiveCount;
4388
4389        /**
4390         * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
4391         */
4392        LongSamplingCounter[] mWifiControllerTime =
4393                new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
4394
4395        /**
4396         * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
4397         */
4398        LongSamplingCounter[] mBluetoothControllerTime =
4399                new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
4400
4401        /**
4402         * The CPU times we had at the last history details update.
4403         */
4404        long mLastStepUserTime;
4405        long mLastStepSystemTime;
4406        long mCurStepUserTime;
4407        long mCurStepSystemTime;
4408
4409        LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
4410        LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
4411        LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase);
4412        LongSamplingCounter[][] mCpuClusterSpeed;
4413
4414        /**
4415         * The statistics we have collected for this uid's wake locks.
4416         */
4417        final OverflowArrayMap<Wakelock> mWakelockStats = new OverflowArrayMap<Wakelock>() {
4418            @Override public Wakelock instantiateObject() { return new Wakelock(); }
4419        };
4420
4421        /**
4422         * The statistics we have collected for this uid's syncs.
4423         */
4424        final OverflowArrayMap<StopwatchTimer> mSyncStats = new OverflowArrayMap<StopwatchTimer>() {
4425            @Override public StopwatchTimer instantiateObject() {
4426                return new StopwatchTimer(Uid.this, SYNC, null, mOnBatteryTimeBase);
4427            }
4428        };
4429
4430        /**
4431         * The statistics we have collected for this uid's jobs.
4432         */
4433        final OverflowArrayMap<StopwatchTimer> mJobStats = new OverflowArrayMap<StopwatchTimer>() {
4434            @Override public StopwatchTimer instantiateObject() {
4435                return new StopwatchTimer(Uid.this, JOB, null, mOnBatteryTimeBase);
4436            }
4437        };
4438
4439        /**
4440         * The statistics we have collected for this uid's sensor activations.
4441         */
4442        final SparseArray<Sensor> mSensorStats = new SparseArray<>();
4443
4444        /**
4445         * The statistics we have collected for this uid's processes.
4446         */
4447        final ArrayMap<String, Proc> mProcessStats = new ArrayMap<>();
4448
4449        /**
4450         * The statistics we have collected for this uid's processes.
4451         */
4452        final ArrayMap<String, Pkg> mPackageStats = new ArrayMap<>();
4453
4454        /**
4455         * The transient wake stats we have collected for this uid's pids.
4456         */
4457        final SparseArray<Pid> mPids = new SparseArray<>();
4458
4459        public Uid(int uid) {
4460            mUid = uid;
4461            mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
4462                    mWifiRunningTimers, mOnBatteryTimeBase);
4463            mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
4464                    mFullWifiLockTimers, mOnBatteryTimeBase);
4465            mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
4466                    mWifiScanTimers, mOnBatteryTimeBase);
4467            mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
4468            mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
4469                    mWifiMulticastTimers, mOnBatteryTimeBase);
4470            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
4471        }
4472
4473        @Override
4474        public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
4475            return mWakelockStats.getMap();
4476        }
4477
4478        @Override
4479        public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
4480            return mSyncStats.getMap();
4481        }
4482
4483        @Override
4484        public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
4485            return mJobStats.getMap();
4486        }
4487
4488        @Override
4489        public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
4490            return mSensorStats;
4491        }
4492
4493        @Override
4494        public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
4495            return mProcessStats;
4496        }
4497
4498        @Override
4499        public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
4500            return mPackageStats;
4501        }
4502
4503        @Override
4504        public int getUid() {
4505            return mUid;
4506        }
4507
4508        @Override
4509        public void noteWifiRunningLocked(long elapsedRealtimeMs) {
4510            if (!mWifiRunning) {
4511                mWifiRunning = true;
4512                if (mWifiRunningTimer == null) {
4513                    mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
4514                            mWifiRunningTimers, mOnBatteryTimeBase);
4515                }
4516                mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
4517            }
4518        }
4519
4520        @Override
4521        public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
4522            if (mWifiRunning) {
4523                mWifiRunning = false;
4524                mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
4525            }
4526        }
4527
4528        @Override
4529        public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
4530            if (!mFullWifiLockOut) {
4531                mFullWifiLockOut = true;
4532                if (mFullWifiLockTimer == null) {
4533                    mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
4534                            mFullWifiLockTimers, mOnBatteryTimeBase);
4535                }
4536                mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
4537            }
4538        }
4539
4540        @Override
4541        public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
4542            if (mFullWifiLockOut) {
4543                mFullWifiLockOut = false;
4544                mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
4545            }
4546        }
4547
4548        @Override
4549        public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
4550            if (!mWifiScanStarted) {
4551                mWifiScanStarted = true;
4552                if (mWifiScanTimer == null) {
4553                    mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
4554                            mWifiScanTimers, mOnBatteryTimeBase);
4555                }
4556                mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
4557            }
4558        }
4559
4560        @Override
4561        public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
4562            if (mWifiScanStarted) {
4563                mWifiScanStarted = false;
4564                mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
4565            }
4566        }
4567
4568        @Override
4569        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
4570            int bin = 0;
4571            while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
4572                csph = csph >> 3;
4573                bin++;
4574            }
4575
4576            if (mWifiBatchedScanBinStarted == bin) return;
4577
4578            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
4579                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
4580                        stopRunningLocked(elapsedRealtimeMs);
4581            }
4582            mWifiBatchedScanBinStarted = bin;
4583            if (mWifiBatchedScanTimer[bin] == null) {
4584                makeWifiBatchedScanBin(bin, null);
4585            }
4586            mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
4587        }
4588
4589        @Override
4590        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
4591            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
4592                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
4593                        stopRunningLocked(elapsedRealtimeMs);
4594                mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
4595            }
4596        }
4597
4598        @Override
4599        public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
4600            if (!mWifiMulticastEnabled) {
4601                mWifiMulticastEnabled = true;
4602                if (mWifiMulticastTimer == null) {
4603                    mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
4604                            mWifiMulticastTimers, mOnBatteryTimeBase);
4605                }
4606                mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
4607            }
4608        }
4609
4610        @Override
4611        public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
4612            if (mWifiMulticastEnabled) {
4613                mWifiMulticastEnabled = false;
4614                mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
4615            }
4616        }
4617
4618        public void noteWifiControllerActivityLocked(int type, long timeMs) {
4619            if (mWifiControllerTime[type] == null) {
4620                mWifiControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase);
4621            }
4622            mWifiControllerTime[type].addCountLocked(timeMs);
4623        }
4624
4625        public StopwatchTimer createAudioTurnedOnTimerLocked() {
4626            if (mAudioTurnedOnTimer == null) {
4627                mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
4628                        mAudioTurnedOnTimers, mOnBatteryTimeBase);
4629            }
4630            return mAudioTurnedOnTimer;
4631        }
4632
4633        public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
4634            createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4635        }
4636
4637        public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
4638            if (mAudioTurnedOnTimer != null) {
4639                mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4640            }
4641        }
4642
4643        public void noteResetAudioLocked(long elapsedRealtimeMs) {
4644            if (mAudioTurnedOnTimer != null) {
4645                mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4646            }
4647        }
4648
4649        public StopwatchTimer createVideoTurnedOnTimerLocked() {
4650            if (mVideoTurnedOnTimer == null) {
4651                mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
4652                        mVideoTurnedOnTimers, mOnBatteryTimeBase);
4653            }
4654            return mVideoTurnedOnTimer;
4655        }
4656
4657        public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
4658            createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4659        }
4660
4661        public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
4662            if (mVideoTurnedOnTimer != null) {
4663                mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4664            }
4665        }
4666
4667        public void noteResetVideoLocked(long elapsedRealtimeMs) {
4668            if (mVideoTurnedOnTimer != null) {
4669                mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4670            }
4671        }
4672
4673        public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
4674            if (mFlashlightTurnedOnTimer == null) {
4675                mFlashlightTurnedOnTimer = new StopwatchTimer(Uid.this, FLASHLIGHT_TURNED_ON,
4676                        mFlashlightTurnedOnTimers, mOnBatteryTimeBase);
4677            }
4678            return mFlashlightTurnedOnTimer;
4679        }
4680
4681        public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
4682            createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4683        }
4684
4685        public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
4686            if (mFlashlightTurnedOnTimer != null) {
4687                mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4688            }
4689        }
4690
4691        public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
4692            if (mFlashlightTurnedOnTimer != null) {
4693                mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4694            }
4695        }
4696
4697        public StopwatchTimer createCameraTurnedOnTimerLocked() {
4698            if (mCameraTurnedOnTimer == null) {
4699                mCameraTurnedOnTimer = new StopwatchTimer(Uid.this, CAMERA_TURNED_ON,
4700                        mCameraTurnedOnTimers, mOnBatteryTimeBase);
4701            }
4702            return mCameraTurnedOnTimer;
4703        }
4704
4705        public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
4706            createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
4707        }
4708
4709        public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
4710            if (mCameraTurnedOnTimer != null) {
4711                mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
4712            }
4713        }
4714
4715        public void noteResetCameraLocked(long elapsedRealtimeMs) {
4716            if (mCameraTurnedOnTimer != null) {
4717                mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
4718            }
4719        }
4720
4721        public StopwatchTimer createForegroundActivityTimerLocked() {
4722            if (mForegroundActivityTimer == null) {
4723                mForegroundActivityTimer = new StopwatchTimer(
4724                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase);
4725            }
4726            return mForegroundActivityTimer;
4727        }
4728
4729        @Override
4730        public void noteActivityResumedLocked(long elapsedRealtimeMs) {
4731            // We always start, since we want multiple foreground PIDs to nest
4732            createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
4733        }
4734
4735        @Override
4736        public void noteActivityPausedLocked(long elapsedRealtimeMs) {
4737            if (mForegroundActivityTimer != null) {
4738                mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
4739            }
4740        }
4741
4742        void updateUidProcessStateLocked(int state, long elapsedRealtimeMs) {
4743            if (mProcessState == state) return;
4744
4745            if (mProcessState != PROCESS_STATE_NONE) {
4746                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
4747            }
4748            mProcessState = state;
4749            if (state != PROCESS_STATE_NONE) {
4750                if (mProcessStateTimer[state] == null) {
4751                    makeProcessState(state, null);
4752                }
4753                mProcessStateTimer[state].startRunningLocked(elapsedRealtimeMs);
4754            }
4755        }
4756
4757        public BatchTimer createVibratorOnTimerLocked() {
4758            if (mVibratorOnTimer == null) {
4759                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
4760            }
4761            return mVibratorOnTimer;
4762        }
4763
4764        public void noteVibratorOnLocked(long durationMillis) {
4765            createVibratorOnTimerLocked().addDuration(BatteryStatsImpl.this, durationMillis);
4766        }
4767
4768        public void noteVibratorOffLocked() {
4769            if (mVibratorOnTimer != null) {
4770                mVibratorOnTimer.abortLastDuration(BatteryStatsImpl.this);
4771            }
4772        }
4773
4774        @Override
4775        public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
4776            if (mWifiRunningTimer == null) {
4777                return 0;
4778            }
4779            return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4780        }
4781
4782        @Override
4783        public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
4784            if (mFullWifiLockTimer == null) {
4785                return 0;
4786            }
4787            return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4788        }
4789
4790        @Override
4791        public long getWifiScanTime(long elapsedRealtimeUs, int which) {
4792            if (mWifiScanTimer == null) {
4793                return 0;
4794            }
4795            return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4796        }
4797
4798        @Override
4799        public int getWifiScanCount(int which) {
4800            if (mWifiScanTimer == null) {
4801                return 0;
4802            }
4803            return mWifiScanTimer.getCountLocked(which);
4804        }
4805
4806        @Override
4807        public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
4808            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
4809            if (mWifiBatchedScanTimer[csphBin] == null) {
4810                return 0;
4811            }
4812            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
4813        }
4814
4815        @Override
4816        public int getWifiBatchedScanCount(int csphBin, int which) {
4817            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
4818            if (mWifiBatchedScanTimer[csphBin] == null) {
4819                return 0;
4820            }
4821            return mWifiBatchedScanTimer[csphBin].getCountLocked(which);
4822        }
4823
4824        @Override
4825        public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
4826            if (mWifiMulticastTimer == null) {
4827                return 0;
4828            }
4829            return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
4830        }
4831
4832        @Override
4833        public Timer getAudioTurnedOnTimer() {
4834            return mAudioTurnedOnTimer;
4835        }
4836
4837        @Override
4838        public Timer getVideoTurnedOnTimer() {
4839            return mVideoTurnedOnTimer;
4840        }
4841
4842        @Override
4843        public Timer getFlashlightTurnedOnTimer() {
4844            return mFlashlightTurnedOnTimer;
4845        }
4846
4847        @Override
4848        public Timer getCameraTurnedOnTimer() {
4849            return mCameraTurnedOnTimer;
4850        }
4851
4852        @Override
4853        public Timer getForegroundActivityTimer() {
4854            return mForegroundActivityTimer;
4855        }
4856
4857        void makeProcessState(int i, Parcel in) {
4858            if (i < 0 || i >= NUM_PROCESS_STATE) return;
4859
4860            if (in == null) {
4861                mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
4862                        mOnBatteryTimeBase);
4863            } else {
4864                mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
4865                        mOnBatteryTimeBase, in);
4866            }
4867        }
4868
4869        @Override
4870        public long getProcessStateTime(int state, long elapsedRealtimeUs, int which) {
4871            if (state < 0 || state >= NUM_PROCESS_STATE) return 0;
4872            if (mProcessStateTimer[state] == null) {
4873                return 0;
4874            }
4875            return mProcessStateTimer[state].getTotalTimeLocked(elapsedRealtimeUs, which);
4876        }
4877
4878        @Override
4879        public Timer getVibratorOnTimer() {
4880            return mVibratorOnTimer;
4881        }
4882
4883        @Override
4884        public void noteUserActivityLocked(int type) {
4885            if (mUserActivityCounters == null) {
4886                initUserActivityLocked();
4887            }
4888            if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) {
4889                mUserActivityCounters[type].stepAtomic();
4890            } else {
4891                Slog.w(TAG, "Unknown user activity type " + type + " was specified.",
4892                        new Throwable());
4893            }
4894        }
4895
4896        @Override
4897        public boolean hasUserActivity() {
4898            return mUserActivityCounters != null;
4899        }
4900
4901        @Override
4902        public int getUserActivityCount(int type, int which) {
4903            if (mUserActivityCounters == null) {
4904                return 0;
4905            }
4906            return mUserActivityCounters[type].getCountLocked(which);
4907        }
4908
4909        void makeWifiBatchedScanBin(int i, Parcel in) {
4910            if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
4911
4912            ArrayList<StopwatchTimer> collected = mWifiBatchedScanTimers.get(i);
4913            if (collected == null) {
4914                collected = new ArrayList<StopwatchTimer>();
4915                mWifiBatchedScanTimers.put(i, collected);
4916            }
4917            if (in == null) {
4918                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
4919                        mOnBatteryTimeBase);
4920            } else {
4921                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
4922                        mOnBatteryTimeBase, in);
4923            }
4924        }
4925
4926
4927        void initUserActivityLocked() {
4928            mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
4929            for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
4930                mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase);
4931            }
4932        }
4933
4934        void noteNetworkActivityLocked(int type, long deltaBytes, long deltaPackets) {
4935            if (mNetworkByteActivityCounters == null) {
4936                initNetworkActivityLocked();
4937            }
4938            if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
4939                mNetworkByteActivityCounters[type].addCountLocked(deltaBytes);
4940                mNetworkPacketActivityCounters[type].addCountLocked(deltaPackets);
4941            } else {
4942                Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
4943                        new Throwable());
4944            }
4945        }
4946
4947        void noteMobileRadioActiveTimeLocked(long batteryUptime) {
4948            if (mNetworkByteActivityCounters == null) {
4949                initNetworkActivityLocked();
4950            }
4951            mMobileRadioActiveTime.addCountLocked(batteryUptime);
4952            mMobileRadioActiveCount.addCountLocked(1);
4953        }
4954
4955        @Override
4956        public boolean hasNetworkActivity() {
4957            return mNetworkByteActivityCounters != null;
4958        }
4959
4960        @Override
4961        public long getNetworkActivityBytes(int type, int which) {
4962            if (mNetworkByteActivityCounters != null && type >= 0
4963                    && type < mNetworkByteActivityCounters.length) {
4964                return mNetworkByteActivityCounters[type].getCountLocked(which);
4965            } else {
4966                return 0;
4967            }
4968        }
4969
4970        @Override
4971        public long getNetworkActivityPackets(int type, int which) {
4972            if (mNetworkPacketActivityCounters != null && type >= 0
4973                    && type < mNetworkPacketActivityCounters.length) {
4974                return mNetworkPacketActivityCounters[type].getCountLocked(which);
4975            } else {
4976                return 0;
4977            }
4978        }
4979
4980        @Override
4981        public long getMobileRadioActiveTime(int which) {
4982            return mMobileRadioActiveTime != null
4983                    ? mMobileRadioActiveTime.getCountLocked(which) : 0;
4984        }
4985
4986        @Override
4987        public int getMobileRadioActiveCount(int which) {
4988            return mMobileRadioActiveCount != null
4989                    ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
4990        }
4991
4992        @Override
4993        public long getUserCpuTimeUs(int which) {
4994            return mUserCpuTime.getCountLocked(which);
4995        }
4996
4997        @Override
4998        public long getSystemCpuTimeUs(int which) {
4999            return mSystemCpuTime.getCountLocked(which);
5000        }
5001
5002        @Override
5003        public long getCpuPowerMaUs(int which) {
5004            return mCpuPower.getCountLocked(which);
5005        }
5006
5007        @Override
5008        public long getTimeAtCpuSpeed(int cluster, int step, int which) {
5009            if (mCpuClusterSpeed != null) {
5010                if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
5011                    final LongSamplingCounter[] cpuSpeeds = mCpuClusterSpeed[cluster];
5012                    if (cpuSpeeds != null) {
5013                        if (step >= 0 && step < cpuSpeeds.length) {
5014                            final LongSamplingCounter c = cpuSpeeds[step];
5015                            if (c != null) {
5016                                return c.getCountLocked(which);
5017                            }
5018                        }
5019                    }
5020                }
5021            }
5022            return 0;
5023        }
5024
5025        @Override
5026        public long getWifiControllerActivity(int type, int which) {
5027            if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES &&
5028                    mWifiControllerTime[type] != null) {
5029                return mWifiControllerTime[type].getCountLocked(which);
5030            }
5031            return 0;
5032        }
5033
5034        void initNetworkActivityLocked() {
5035            mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5036            mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5037            for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5038                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
5039                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
5040            }
5041            mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase);
5042            mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase);
5043        }
5044
5045        /**
5046         * Clear all stats for this uid.  Returns true if the uid is completely
5047         * inactive so can be dropped.
5048         */
5049        boolean reset() {
5050            boolean active = false;
5051
5052            if (mWifiRunningTimer != null) {
5053                active |= !mWifiRunningTimer.reset(false);
5054                active |= mWifiRunning;
5055            }
5056            if (mFullWifiLockTimer != null) {
5057                active |= !mFullWifiLockTimer.reset(false);
5058                active |= mFullWifiLockOut;
5059            }
5060            if (mWifiScanTimer != null) {
5061                active |= !mWifiScanTimer.reset(false);
5062                active |= mWifiScanStarted;
5063            }
5064            if (mWifiBatchedScanTimer != null) {
5065                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5066                    if (mWifiBatchedScanTimer[i] != null) {
5067                        active |= !mWifiBatchedScanTimer[i].reset(false);
5068                    }
5069                }
5070                active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
5071            }
5072            if (mWifiMulticastTimer != null) {
5073                active |= !mWifiMulticastTimer.reset(false);
5074                active |= mWifiMulticastEnabled;
5075            }
5076            if (mAudioTurnedOnTimer != null) {
5077                active |= !mAudioTurnedOnTimer.reset(false);
5078            }
5079            if (mVideoTurnedOnTimer != null) {
5080                active |= !mVideoTurnedOnTimer.reset(false);
5081            }
5082            if (mFlashlightTurnedOnTimer != null) {
5083                active |= !mFlashlightTurnedOnTimer.reset(false);
5084            }
5085            if (mCameraTurnedOnTimer != null) {
5086                active |= !mCameraTurnedOnTimer.reset(false);
5087            }
5088            if (mForegroundActivityTimer != null) {
5089                active |= !mForegroundActivityTimer.reset(false);
5090            }
5091            if (mProcessStateTimer != null) {
5092                for (int i = 0; i < NUM_PROCESS_STATE; i++) {
5093                    if (mProcessStateTimer[i] != null) {
5094                        active |= !mProcessStateTimer[i].reset(false);
5095                    }
5096                }
5097                active |= (mProcessState != PROCESS_STATE_NONE);
5098            }
5099            if (mVibratorOnTimer != null) {
5100                if (mVibratorOnTimer.reset(false)) {
5101                    mVibratorOnTimer.detach();
5102                    mVibratorOnTimer = null;
5103                } else {
5104                    active = true;
5105                }
5106            }
5107
5108            if (mUserActivityCounters != null) {
5109                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5110                    mUserActivityCounters[i].reset(false);
5111                }
5112            }
5113
5114            if (mNetworkByteActivityCounters != null) {
5115                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5116                    mNetworkByteActivityCounters[i].reset(false);
5117                    mNetworkPacketActivityCounters[i].reset(false);
5118                }
5119                mMobileRadioActiveTime.reset(false);
5120                mMobileRadioActiveCount.reset(false);
5121            }
5122
5123            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5124                if (mWifiControllerTime[i] != null) {
5125                    mWifiControllerTime[i].reset(false);
5126                }
5127
5128                if (mBluetoothControllerTime[i] != null) {
5129                    mBluetoothControllerTime[i].reset(false);
5130                }
5131            }
5132
5133            mUserCpuTime.reset(false);
5134            mSystemCpuTime.reset(false);
5135            mCpuPower.reset(false);
5136
5137            if (mCpuClusterSpeed != null) {
5138                for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
5139                    if (speeds != null) {
5140                        for (LongSamplingCounter speed : speeds) {
5141                            if (speed != null) {
5142                                speed.reset(false);
5143                            }
5144                        }
5145                    }
5146                }
5147            }
5148
5149            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
5150            for (int iw=wakeStats.size()-1; iw>=0; iw--) {
5151                Wakelock wl = wakeStats.valueAt(iw);
5152                if (wl.reset()) {
5153                    wakeStats.removeAt(iw);
5154                } else {
5155                    active = true;
5156                }
5157            }
5158            mWakelockStats.cleanup();
5159            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
5160            for (int is=syncStats.size()-1; is>=0; is--) {
5161                StopwatchTimer timer = syncStats.valueAt(is);
5162                if (timer.reset(false)) {
5163                    syncStats.removeAt(is);
5164                    timer.detach();
5165                } else {
5166                    active = true;
5167                }
5168            }
5169            mSyncStats.cleanup();
5170            final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
5171            for (int ij=jobStats.size()-1; ij>=0; ij--) {
5172                StopwatchTimer timer = jobStats.valueAt(ij);
5173                if (timer.reset(false)) {
5174                    jobStats.removeAt(ij);
5175                    timer.detach();
5176                } else {
5177                    active = true;
5178                }
5179            }
5180            mJobStats.cleanup();
5181            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
5182                Sensor s = mSensorStats.valueAt(ise);
5183                if (s.reset()) {
5184                    mSensorStats.removeAt(ise);
5185                } else {
5186                    active = true;
5187                }
5188            }
5189            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
5190                Proc proc = mProcessStats.valueAt(ip);
5191                if (proc.mProcessState == PROCESS_STATE_NONE) {
5192                    proc.detach();
5193                    mProcessStats.removeAt(ip);
5194                } else {
5195                    proc.reset();
5196                    active = true;
5197                }
5198            }
5199            if (mPids.size() > 0) {
5200                for (int i=mPids.size()-1; i>=0; i--) {
5201                    Pid pid = mPids.valueAt(i);
5202                    if (pid.mWakeNesting > 0) {
5203                        active = true;
5204                    } else {
5205                        mPids.removeAt(i);
5206                    }
5207                }
5208            }
5209            if (mPackageStats.size() > 0) {
5210                Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
5211                while (it.hasNext()) {
5212                    Map.Entry<String, Pkg> pkgEntry = it.next();
5213                    Pkg p = pkgEntry.getValue();
5214                    p.detach();
5215                    if (p.mServiceStats.size() > 0) {
5216                        Iterator<Map.Entry<String, Pkg.Serv>> it2
5217                                = p.mServiceStats.entrySet().iterator();
5218                        while (it2.hasNext()) {
5219                            Map.Entry<String, Pkg.Serv> servEntry = it2.next();
5220                            servEntry.getValue().detach();
5221                        }
5222                    }
5223                }
5224                mPackageStats.clear();
5225            }
5226
5227            mLastStepUserTime = mLastStepSystemTime = 0;
5228            mCurStepUserTime = mCurStepSystemTime = 0;
5229
5230            if (!active) {
5231                if (mWifiRunningTimer != null) {
5232                    mWifiRunningTimer.detach();
5233                }
5234                if (mFullWifiLockTimer != null) {
5235                    mFullWifiLockTimer.detach();
5236                }
5237                if (mWifiScanTimer != null) {
5238                    mWifiScanTimer.detach();
5239                }
5240                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5241                    if (mWifiBatchedScanTimer[i] != null) {
5242                        mWifiBatchedScanTimer[i].detach();
5243                    }
5244                }
5245                if (mWifiMulticastTimer != null) {
5246                    mWifiMulticastTimer.detach();
5247                }
5248                if (mAudioTurnedOnTimer != null) {
5249                    mAudioTurnedOnTimer.detach();
5250                    mAudioTurnedOnTimer = null;
5251                }
5252                if (mVideoTurnedOnTimer != null) {
5253                    mVideoTurnedOnTimer.detach();
5254                    mVideoTurnedOnTimer = null;
5255                }
5256                if (mFlashlightTurnedOnTimer != null) {
5257                    mFlashlightTurnedOnTimer.detach();
5258                    mFlashlightTurnedOnTimer = null;
5259                }
5260                if (mCameraTurnedOnTimer != null) {
5261                    mCameraTurnedOnTimer.detach();
5262                    mCameraTurnedOnTimer = null;
5263                }
5264                if (mForegroundActivityTimer != null) {
5265                    mForegroundActivityTimer.detach();
5266                    mForegroundActivityTimer = null;
5267                }
5268                if (mUserActivityCounters != null) {
5269                    for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5270                        mUserActivityCounters[i].detach();
5271                    }
5272                }
5273                if (mNetworkByteActivityCounters != null) {
5274                    for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5275                        mNetworkByteActivityCounters[i].detach();
5276                        mNetworkPacketActivityCounters[i].detach();
5277                    }
5278                }
5279
5280                for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5281                    if (mWifiControllerTime[i] != null) {
5282                        mWifiControllerTime[i].detach();
5283                    }
5284
5285                    if (mBluetoothControllerTime[i] != null) {
5286                        mBluetoothControllerTime[i].detach();
5287                    }
5288                }
5289                mPids.clear();
5290
5291                mUserCpuTime.detach();
5292                mSystemCpuTime.detach();
5293                mCpuPower.detach();
5294
5295                if (mCpuClusterSpeed != null) {
5296                    for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
5297                        if (cpuSpeeds != null) {
5298                            for (LongSamplingCounter c : cpuSpeeds) {
5299                                if (c != null) {
5300                                    c.detach();
5301                                }
5302                            }
5303                        }
5304                    }
5305                }
5306            }
5307
5308            return !active;
5309        }
5310
5311        void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
5312            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
5313            int NW = wakeStats.size();
5314            out.writeInt(NW);
5315            for (int iw=0; iw<NW; iw++) {
5316                out.writeString(wakeStats.keyAt(iw));
5317                Uid.Wakelock wakelock = wakeStats.valueAt(iw);
5318                wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
5319            }
5320
5321            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
5322            int NS = syncStats.size();
5323            out.writeInt(NS);
5324            for (int is=0; is<NS; is++) {
5325                out.writeString(syncStats.keyAt(is));
5326                StopwatchTimer timer = syncStats.valueAt(is);
5327                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
5328            }
5329
5330            final ArrayMap<String, StopwatchTimer> jobStats = mJobStats.getMap();
5331            int NJ = jobStats.size();
5332            out.writeInt(NJ);
5333            for (int ij=0; ij<NJ; ij++) {
5334                out.writeString(jobStats.keyAt(ij));
5335                StopwatchTimer timer = jobStats.valueAt(ij);
5336                Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
5337            }
5338
5339            int NSE = mSensorStats.size();
5340            out.writeInt(NSE);
5341            for (int ise=0; ise<NSE; ise++) {
5342                out.writeInt(mSensorStats.keyAt(ise));
5343                Uid.Sensor sensor = mSensorStats.valueAt(ise);
5344                sensor.writeToParcelLocked(out, elapsedRealtimeUs);
5345            }
5346
5347            int NP = mProcessStats.size();
5348            out.writeInt(NP);
5349            for (int ip=0; ip<NP; ip++) {
5350                out.writeString(mProcessStats.keyAt(ip));
5351                Uid.Proc proc = mProcessStats.valueAt(ip);
5352                proc.writeToParcelLocked(out);
5353            }
5354
5355            out.writeInt(mPackageStats.size());
5356            for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
5357                out.writeString(pkgEntry.getKey());
5358                Uid.Pkg pkg = pkgEntry.getValue();
5359                pkg.writeToParcelLocked(out);
5360            }
5361
5362            if (mWifiRunningTimer != null) {
5363                out.writeInt(1);
5364                mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
5365            } else {
5366                out.writeInt(0);
5367            }
5368            if (mFullWifiLockTimer != null) {
5369                out.writeInt(1);
5370                mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
5371            } else {
5372                out.writeInt(0);
5373            }
5374            if (mWifiScanTimer != null) {
5375                out.writeInt(1);
5376                mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
5377            } else {
5378                out.writeInt(0);
5379            }
5380            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5381                if (mWifiBatchedScanTimer[i] != null) {
5382                    out.writeInt(1);
5383                    mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
5384                } else {
5385                    out.writeInt(0);
5386                }
5387            }
5388            if (mWifiMulticastTimer != null) {
5389                out.writeInt(1);
5390                mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
5391            } else {
5392                out.writeInt(0);
5393            }
5394
5395            if (mAudioTurnedOnTimer != null) {
5396                out.writeInt(1);
5397                mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5398            } else {
5399                out.writeInt(0);
5400            }
5401            if (mVideoTurnedOnTimer != null) {
5402                out.writeInt(1);
5403                mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5404            } else {
5405                out.writeInt(0);
5406            }
5407            if (mFlashlightTurnedOnTimer != null) {
5408                out.writeInt(1);
5409                mFlashlightTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5410            } else {
5411                out.writeInt(0);
5412            }
5413            if (mCameraTurnedOnTimer != null) {
5414                out.writeInt(1);
5415                mCameraTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
5416            } else {
5417                out.writeInt(0);
5418            }
5419            if (mForegroundActivityTimer != null) {
5420                out.writeInt(1);
5421                mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
5422            } else {
5423                out.writeInt(0);
5424            }
5425            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
5426                if (mProcessStateTimer[i] != null) {
5427                    out.writeInt(1);
5428                    mProcessStateTimer[i].writeToParcel(out, elapsedRealtimeUs);
5429                } else {
5430                    out.writeInt(0);
5431                }
5432            }
5433            if (mVibratorOnTimer != null) {
5434                out.writeInt(1);
5435                mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
5436            } else {
5437                out.writeInt(0);
5438            }
5439            if (mUserActivityCounters != null) {
5440                out.writeInt(1);
5441                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5442                    mUserActivityCounters[i].writeToParcel(out);
5443                }
5444            } else {
5445                out.writeInt(0);
5446            }
5447            if (mNetworkByteActivityCounters != null) {
5448                out.writeInt(1);
5449                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5450                    mNetworkByteActivityCounters[i].writeToParcel(out);
5451                    mNetworkPacketActivityCounters[i].writeToParcel(out);
5452                }
5453                mMobileRadioActiveTime.writeToParcel(out);
5454                mMobileRadioActiveCount.writeToParcel(out);
5455            } else {
5456                out.writeInt(0);
5457            }
5458
5459            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5460                if (mWifiControllerTime[i] != null) {
5461                    out.writeInt(1);
5462                    mWifiControllerTime[i].writeToParcel(out);
5463                } else {
5464                    out.writeInt(0);
5465                }
5466            }
5467
5468            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5469                if (mBluetoothControllerTime[i] != null) {
5470                    out.writeInt(1);
5471                    mBluetoothControllerTime[i].writeToParcel(out);
5472                } else {
5473                    out.writeInt(0);
5474                }
5475            }
5476
5477            mUserCpuTime.writeToParcel(out);
5478            mSystemCpuTime.writeToParcel(out);
5479            mCpuPower.writeToParcel(out);
5480
5481            if (mCpuClusterSpeed != null) {
5482                out.writeInt(1);
5483                out.writeInt(mCpuClusterSpeed.length);
5484                for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
5485                    if (cpuSpeeds != null) {
5486                        out.writeInt(1);
5487                        out.writeInt(cpuSpeeds.length);
5488                        for (LongSamplingCounter c : cpuSpeeds) {
5489                            if (c != null) {
5490                                out.writeInt(1);
5491                                c.writeToParcel(out);
5492                            } else {
5493                                out.writeInt(0);
5494                            }
5495                        }
5496                    } else {
5497                        out.writeInt(0);
5498                    }
5499                }
5500            } else {
5501                out.writeInt(0);
5502            }
5503        }
5504
5505        void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
5506            int numWakelocks = in.readInt();
5507            mWakelockStats.clear();
5508            for (int j = 0; j < numWakelocks; j++) {
5509                String wakelockName = in.readString();
5510                Uid.Wakelock wakelock = new Wakelock();
5511                wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
5512                mWakelockStats.add(wakelockName, wakelock);
5513            }
5514
5515            int numSyncs = in.readInt();
5516            mSyncStats.clear();
5517            for (int j = 0; j < numSyncs; j++) {
5518                String syncName = in.readString();
5519                if (in.readInt() != 0) {
5520                    mSyncStats.add(syncName,
5521                            new StopwatchTimer(Uid.this, SYNC, null, timeBase, in));
5522                }
5523            }
5524
5525            int numJobs = in.readInt();
5526            mJobStats.clear();
5527            for (int j = 0; j < numJobs; j++) {
5528                String jobName = in.readString();
5529                if (in.readInt() != 0) {
5530                    mJobStats.add(jobName, new StopwatchTimer(Uid.this, JOB, null, timeBase, in));
5531                }
5532            }
5533
5534            int numSensors = in.readInt();
5535            mSensorStats.clear();
5536            for (int k = 0; k < numSensors; k++) {
5537                int sensorNumber = in.readInt();
5538                Uid.Sensor sensor = new Sensor(sensorNumber);
5539                sensor.readFromParcelLocked(mOnBatteryTimeBase, in);
5540                mSensorStats.put(sensorNumber, sensor);
5541            }
5542
5543            int numProcs = in.readInt();
5544            mProcessStats.clear();
5545            for (int k = 0; k < numProcs; k++) {
5546                String processName = in.readString();
5547                Uid.Proc proc = new Proc(processName);
5548                proc.readFromParcelLocked(in);
5549                mProcessStats.put(processName, proc);
5550            }
5551
5552            int numPkgs = in.readInt();
5553            mPackageStats.clear();
5554            for (int l = 0; l < numPkgs; l++) {
5555                String packageName = in.readString();
5556                Uid.Pkg pkg = new Pkg();
5557                pkg.readFromParcelLocked(in);
5558                mPackageStats.put(packageName, pkg);
5559            }
5560
5561            mWifiRunning = false;
5562            if (in.readInt() != 0) {
5563                mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
5564                        mWifiRunningTimers, mOnBatteryTimeBase, in);
5565            } else {
5566                mWifiRunningTimer = null;
5567            }
5568            mFullWifiLockOut = false;
5569            if (in.readInt() != 0) {
5570                mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
5571                        mFullWifiLockTimers, mOnBatteryTimeBase, in);
5572            } else {
5573                mFullWifiLockTimer = null;
5574            }
5575            mWifiScanStarted = false;
5576            if (in.readInt() != 0) {
5577                mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
5578                        mWifiScanTimers, mOnBatteryTimeBase, in);
5579            } else {
5580                mWifiScanTimer = null;
5581            }
5582            mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
5583            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
5584                if (in.readInt() != 0) {
5585                    makeWifiBatchedScanBin(i, in);
5586                } else {
5587                    mWifiBatchedScanTimer[i] = null;
5588                }
5589            }
5590            mWifiMulticastEnabled = false;
5591            if (in.readInt() != 0) {
5592                mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
5593                        mWifiMulticastTimers, mOnBatteryTimeBase, in);
5594            } else {
5595                mWifiMulticastTimer = null;
5596            }
5597            if (in.readInt() != 0) {
5598                mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
5599                        mAudioTurnedOnTimers, mOnBatteryTimeBase, in);
5600            } else {
5601                mAudioTurnedOnTimer = null;
5602            }
5603            if (in.readInt() != 0) {
5604                mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
5605                        mVideoTurnedOnTimers, mOnBatteryTimeBase, in);
5606            } else {
5607                mVideoTurnedOnTimer = null;
5608            }
5609            if (in.readInt() != 0) {
5610                mFlashlightTurnedOnTimer = new StopwatchTimer(Uid.this, FLASHLIGHT_TURNED_ON,
5611                        mFlashlightTurnedOnTimers, mOnBatteryTimeBase, in);
5612            } else {
5613                mFlashlightTurnedOnTimer = null;
5614            }
5615            if (in.readInt() != 0) {
5616                mCameraTurnedOnTimer = new StopwatchTimer(Uid.this, CAMERA_TURNED_ON,
5617                        mCameraTurnedOnTimers, mOnBatteryTimeBase, in);
5618            } else {
5619                mCameraTurnedOnTimer = null;
5620            }
5621            if (in.readInt() != 0) {
5622                mForegroundActivityTimer = new StopwatchTimer(
5623                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase, in);
5624            } else {
5625                mForegroundActivityTimer = null;
5626            }
5627            mProcessState = PROCESS_STATE_NONE;
5628            for (int i = 0; i < NUM_PROCESS_STATE; i++) {
5629                if (in.readInt() != 0) {
5630                    makeProcessState(i, in);
5631                } else {
5632                    mProcessStateTimer[i] = null;
5633                }
5634            }
5635            if (in.readInt() != 0) {
5636                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase, in);
5637            } else {
5638                mVibratorOnTimer = null;
5639            }
5640            if (in.readInt() != 0) {
5641                mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
5642                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
5643                    mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase, in);
5644                }
5645            } else {
5646                mUserActivityCounters = null;
5647            }
5648            if (in.readInt() != 0) {
5649                mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5650                mNetworkPacketActivityCounters
5651                        = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
5652                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
5653                    mNetworkByteActivityCounters[i]
5654                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
5655                    mNetworkPacketActivityCounters[i]
5656                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
5657                }
5658                mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
5659                mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
5660            } else {
5661                mNetworkByteActivityCounters = null;
5662                mNetworkPacketActivityCounters = null;
5663            }
5664
5665            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5666                if (in.readInt() != 0) {
5667                    mWifiControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
5668                } else {
5669                    mWifiControllerTime[i] = null;
5670                }
5671            }
5672
5673            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
5674                if (in.readInt() != 0) {
5675                    mBluetoothControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
5676                } else {
5677                    mBluetoothControllerTime[i] = null;
5678                }
5679            }
5680
5681            mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
5682            mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
5683            mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in);
5684
5685            if (in.readInt() != 0) {
5686                int numCpuClusters = in.readInt();
5687                if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numCpuClusters) {
5688                    throw new ParcelFormatException("Incompatible number of cpu clusters");
5689                }
5690
5691                mCpuClusterSpeed = new LongSamplingCounter[numCpuClusters][];
5692                for (int cluster = 0; cluster < numCpuClusters; cluster++) {
5693                    if (in.readInt() != 0) {
5694                        int numSpeeds = in.readInt();
5695                        if (mPowerProfile != null &&
5696                                mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
5697                            throw new ParcelFormatException("Incompatible number of cpu speeds");
5698                        }
5699
5700                        final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
5701                        mCpuClusterSpeed[cluster] = cpuSpeeds;
5702                        for (int speed = 0; speed < numSpeeds; speed++) {
5703                            if (in.readInt() != 0) {
5704                                cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase, in);
5705                            }
5706                        }
5707                    } else {
5708                        mCpuClusterSpeed[cluster] = null;
5709                    }
5710                }
5711            } else {
5712                mCpuClusterSpeed = null;
5713            }
5714        }
5715
5716        /**
5717         * The statistics associated with a particular wake lock.
5718         */
5719        public final class Wakelock extends BatteryStats.Uid.Wakelock {
5720            /**
5721             * How long (in ms) this uid has been keeping the device partially awake.
5722             */
5723            StopwatchTimer mTimerPartial;
5724
5725            /**
5726             * How long (in ms) this uid has been keeping the device fully awake.
5727             */
5728            StopwatchTimer mTimerFull;
5729
5730            /**
5731             * How long (in ms) this uid has had a window keeping the device awake.
5732             */
5733            StopwatchTimer mTimerWindow;
5734
5735            /**
5736             * How long (in ms) this uid has had a draw wake lock.
5737             */
5738            StopwatchTimer mTimerDraw;
5739
5740            /**
5741             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
5742             * proper timer pool from the given BatteryStatsImpl object.
5743             *
5744             * @param in the Parcel to be read from.
5745             * return a new Timer, or null.
5746             */
5747            private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
5748                    TimeBase timeBase, Parcel in) {
5749                if (in.readInt() == 0) {
5750                    return null;
5751                }
5752
5753                return new StopwatchTimer(Uid.this, type, pool, timeBase, in);
5754            }
5755
5756            boolean reset() {
5757                boolean wlactive = false;
5758                if (mTimerFull != null) {
5759                    wlactive |= !mTimerFull.reset(false);
5760                }
5761                if (mTimerPartial != null) {
5762                    wlactive |= !mTimerPartial.reset(false);
5763                }
5764                if (mTimerWindow != null) {
5765                    wlactive |= !mTimerWindow.reset(false);
5766                }
5767                if (mTimerDraw != null) {
5768                    wlactive |= !mTimerDraw.reset(false);
5769                }
5770                if (!wlactive) {
5771                    if (mTimerFull != null) {
5772                        mTimerFull.detach();
5773                        mTimerFull = null;
5774                    }
5775                    if (mTimerPartial != null) {
5776                        mTimerPartial.detach();
5777                        mTimerPartial = null;
5778                    }
5779                    if (mTimerWindow != null) {
5780                        mTimerWindow.detach();
5781                        mTimerWindow = null;
5782                    }
5783                    if (mTimerDraw != null) {
5784                        mTimerDraw.detach();
5785                        mTimerDraw = null;
5786                    }
5787                }
5788                return !wlactive;
5789            }
5790
5791            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
5792                mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
5793                        mPartialTimers, screenOffTimeBase, in);
5794                mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, mFullTimers, timeBase, in);
5795                mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, mWindowTimers, timeBase, in);
5796                mTimerDraw = readTimerFromParcel(WAKE_TYPE_DRAW, mDrawTimers, timeBase, in);
5797            }
5798
5799            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
5800                Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
5801                Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
5802                Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
5803                Timer.writeTimerToParcel(out, mTimerDraw, elapsedRealtimeUs);
5804            }
5805
5806            @Override
5807            public Timer getWakeTime(int type) {
5808                switch (type) {
5809                case WAKE_TYPE_FULL: return mTimerFull;
5810                case WAKE_TYPE_PARTIAL: return mTimerPartial;
5811                case WAKE_TYPE_WINDOW: return mTimerWindow;
5812                case WAKE_TYPE_DRAW: return mTimerDraw;
5813                default: throw new IllegalArgumentException("type = " + type);
5814                }
5815            }
5816
5817            public StopwatchTimer getStopwatchTimer(int type) {
5818                StopwatchTimer t;
5819                switch (type) {
5820                    case WAKE_TYPE_PARTIAL:
5821                        t = mTimerPartial;
5822                        if (t == null) {
5823                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
5824                                    mPartialTimers, mOnBatteryScreenOffTimeBase);
5825                            mTimerPartial = t;
5826                        }
5827                        return t;
5828                    case WAKE_TYPE_FULL:
5829                        t = mTimerFull;
5830                        if (t == null) {
5831                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
5832                                    mFullTimers, mOnBatteryTimeBase);
5833                            mTimerFull = t;
5834                        }
5835                        return t;
5836                    case WAKE_TYPE_WINDOW:
5837                        t = mTimerWindow;
5838                        if (t == null) {
5839                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
5840                                    mWindowTimers, mOnBatteryTimeBase);
5841                            mTimerWindow = t;
5842                        }
5843                        return t;
5844                    case WAKE_TYPE_DRAW:
5845                        t = mTimerDraw;
5846                        if (t == null) {
5847                            t = new StopwatchTimer(Uid.this, WAKE_TYPE_DRAW,
5848                                    mDrawTimers, mOnBatteryTimeBase);
5849                            mTimerDraw = t;
5850                        }
5851                        return t;
5852                    default:
5853                        throw new IllegalArgumentException("type=" + type);
5854                }
5855            }
5856        }
5857
5858        public final class Sensor extends BatteryStats.Uid.Sensor {
5859            final int mHandle;
5860            StopwatchTimer mTimer;
5861
5862            public Sensor(int handle) {
5863                mHandle = handle;
5864            }
5865
5866            private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) {
5867                if (in.readInt() == 0) {
5868                    return null;
5869                }
5870
5871                ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
5872                if (pool == null) {
5873                    pool = new ArrayList<StopwatchTimer>();
5874                    mSensorTimers.put(mHandle, pool);
5875                }
5876                return new StopwatchTimer(Uid.this, 0, pool, timeBase, in);
5877            }
5878
5879            boolean reset() {
5880                if (mTimer.reset(true)) {
5881                    mTimer = null;
5882                    return true;
5883                }
5884                return false;
5885            }
5886
5887            void readFromParcelLocked(TimeBase timeBase, Parcel in) {
5888                mTimer = readTimerFromParcel(timeBase, in);
5889            }
5890
5891            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
5892                Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
5893            }
5894
5895            @Override
5896            public Timer getSensorTime() {
5897                return mTimer;
5898            }
5899
5900            @Override
5901            public int getHandle() {
5902                return mHandle;
5903            }
5904        }
5905
5906        /**
5907         * The statistics associated with a particular process.
5908         */
5909        public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
5910            /**
5911             * The name of this process.
5912             */
5913            final String mName;
5914
5915            /**
5916             * Remains true until removed from the stats.
5917             */
5918            boolean mActive = true;
5919
5920            /**
5921             * Total time (in ms) spent executing in user code.
5922             */
5923            long mUserTime;
5924
5925            /**
5926             * Total time (in ms) spent executing in kernel code.
5927             */
5928            long mSystemTime;
5929
5930            /**
5931             * Amount of time (in ms) the process was running in the foreground.
5932             */
5933            long mForegroundTime;
5934
5935            /**
5936             * Number of times the process has been started.
5937             */
5938            int mStarts;
5939
5940            /**
5941             * Number of times the process has crashed.
5942             */
5943            int mNumCrashes;
5944
5945            /**
5946             * Number of times the process has had an ANR.
5947             */
5948            int mNumAnrs;
5949
5950            /**
5951             * The amount of user time loaded from a previous save.
5952             */
5953            long mLoadedUserTime;
5954
5955            /**
5956             * The amount of system time loaded from a previous save.
5957             */
5958            long mLoadedSystemTime;
5959
5960            /**
5961             * The amount of foreground time loaded from a previous save.
5962             */
5963            long mLoadedForegroundTime;
5964
5965            /**
5966             * The number of times the process has started from a previous save.
5967             */
5968            int mLoadedStarts;
5969
5970            /**
5971             * Number of times the process has crashed from a previous save.
5972             */
5973            int mLoadedNumCrashes;
5974
5975            /**
5976             * Number of times the process has had an ANR from a previous save.
5977             */
5978            int mLoadedNumAnrs;
5979
5980            /**
5981             * The amount of user time when last unplugged.
5982             */
5983            long mUnpluggedUserTime;
5984
5985            /**
5986             * The amount of system time when last unplugged.
5987             */
5988            long mUnpluggedSystemTime;
5989
5990            /**
5991             * The amount of foreground time since unplugged.
5992             */
5993            long mUnpluggedForegroundTime;
5994
5995            /**
5996             * The number of times the process has started before unplugged.
5997             */
5998            int mUnpluggedStarts;
5999
6000            /**
6001             * Number of times the process has crashed before unplugged.
6002             */
6003            int mUnpluggedNumCrashes;
6004
6005            /**
6006             * Number of times the process has had an ANR before unplugged.
6007             */
6008            int mUnpluggedNumAnrs;
6009
6010            /**
6011             * Current process state.
6012             */
6013            int mProcessState = PROCESS_STATE_NONE;
6014
6015            ArrayList<ExcessivePower> mExcessivePower;
6016
6017            Proc(String name) {
6018                mName = name;
6019                mOnBatteryTimeBase.add(this);
6020            }
6021
6022            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
6023                mUnpluggedUserTime = mUserTime;
6024                mUnpluggedSystemTime = mSystemTime;
6025                mUnpluggedForegroundTime = mForegroundTime;
6026                mUnpluggedStarts = mStarts;
6027                mUnpluggedNumCrashes = mNumCrashes;
6028                mUnpluggedNumAnrs = mNumAnrs;
6029            }
6030
6031            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
6032            }
6033
6034            void reset() {
6035                mUserTime = mSystemTime = mForegroundTime = 0;
6036                mStarts = mNumCrashes = mNumAnrs = 0;
6037                mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0;
6038                mLoadedStarts = mLoadedNumCrashes = mLoadedNumAnrs = 0;
6039                mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0;
6040                mUnpluggedStarts = mUnpluggedNumCrashes = mUnpluggedNumAnrs = 0;
6041                mExcessivePower = null;
6042            }
6043
6044            void detach() {
6045                mActive = false;
6046                mOnBatteryTimeBase.remove(this);
6047            }
6048
6049            public int countExcessivePowers() {
6050                return mExcessivePower != null ? mExcessivePower.size() : 0;
6051            }
6052
6053            public ExcessivePower getExcessivePower(int i) {
6054                if (mExcessivePower != null) {
6055                    return mExcessivePower.get(i);
6056                }
6057                return null;
6058            }
6059
6060            public void addExcessiveWake(long overTime, long usedTime) {
6061                if (mExcessivePower == null) {
6062                    mExcessivePower = new ArrayList<ExcessivePower>();
6063                }
6064                ExcessivePower ew = new ExcessivePower();
6065                ew.type = ExcessivePower.TYPE_WAKE;
6066                ew.overTime = overTime;
6067                ew.usedTime = usedTime;
6068                mExcessivePower.add(ew);
6069            }
6070
6071            public void addExcessiveCpu(long overTime, long usedTime) {
6072                if (mExcessivePower == null) {
6073                    mExcessivePower = new ArrayList<ExcessivePower>();
6074                }
6075                ExcessivePower ew = new ExcessivePower();
6076                ew.type = ExcessivePower.TYPE_CPU;
6077                ew.overTime = overTime;
6078                ew.usedTime = usedTime;
6079                mExcessivePower.add(ew);
6080            }
6081
6082            void writeExcessivePowerToParcelLocked(Parcel out) {
6083                if (mExcessivePower == null) {
6084                    out.writeInt(0);
6085                    return;
6086                }
6087
6088                final int N = mExcessivePower.size();
6089                out.writeInt(N);
6090                for (int i=0; i<N; i++) {
6091                    ExcessivePower ew = mExcessivePower.get(i);
6092                    out.writeInt(ew.type);
6093                    out.writeLong(ew.overTime);
6094                    out.writeLong(ew.usedTime);
6095                }
6096            }
6097
6098            void readExcessivePowerFromParcelLocked(Parcel in) {
6099                final int N = in.readInt();
6100                if (N == 0) {
6101                    mExcessivePower = null;
6102                    return;
6103                }
6104
6105                if (N > 10000) {
6106                    throw new ParcelFormatException(
6107                            "File corrupt: too many excessive power entries " + N);
6108                }
6109
6110                mExcessivePower = new ArrayList<>();
6111                for (int i=0; i<N; i++) {
6112                    ExcessivePower ew = new ExcessivePower();
6113                    ew.type = in.readInt();
6114                    ew.overTime = in.readLong();
6115                    ew.usedTime = in.readLong();
6116                    mExcessivePower.add(ew);
6117                }
6118            }
6119
6120            void writeToParcelLocked(Parcel out) {
6121                out.writeLong(mUserTime);
6122                out.writeLong(mSystemTime);
6123                out.writeLong(mForegroundTime);
6124                out.writeInt(mStarts);
6125                out.writeInt(mNumCrashes);
6126                out.writeInt(mNumAnrs);
6127                out.writeLong(mLoadedUserTime);
6128                out.writeLong(mLoadedSystemTime);
6129                out.writeLong(mLoadedForegroundTime);
6130                out.writeInt(mLoadedStarts);
6131                out.writeInt(mLoadedNumCrashes);
6132                out.writeInt(mLoadedNumAnrs);
6133                out.writeLong(mUnpluggedUserTime);
6134                out.writeLong(mUnpluggedSystemTime);
6135                out.writeLong(mUnpluggedForegroundTime);
6136                out.writeInt(mUnpluggedStarts);
6137                out.writeInt(mUnpluggedNumCrashes);
6138                out.writeInt(mUnpluggedNumAnrs);
6139                writeExcessivePowerToParcelLocked(out);
6140            }
6141
6142            void readFromParcelLocked(Parcel in) {
6143                mUserTime = in.readLong();
6144                mSystemTime = in.readLong();
6145                mForegroundTime = in.readLong();
6146                mStarts = in.readInt();
6147                mNumCrashes = in.readInt();
6148                mNumAnrs = in.readInt();
6149                mLoadedUserTime = in.readLong();
6150                mLoadedSystemTime = in.readLong();
6151                mLoadedForegroundTime = in.readLong();
6152                mLoadedStarts = in.readInt();
6153                mLoadedNumCrashes = in.readInt();
6154                mLoadedNumAnrs = in.readInt();
6155                mUnpluggedUserTime = in.readLong();
6156                mUnpluggedSystemTime = in.readLong();
6157                mUnpluggedForegroundTime = in.readLong();
6158                mUnpluggedStarts = in.readInt();
6159                mUnpluggedNumCrashes = in.readInt();
6160                mUnpluggedNumAnrs = in.readInt();
6161                readExcessivePowerFromParcelLocked(in);
6162            }
6163
6164            public void addCpuTimeLocked(int utime, int stime) {
6165                mUserTime += utime;
6166                mSystemTime += stime;
6167            }
6168
6169            public void addForegroundTimeLocked(long ttime) {
6170                mForegroundTime += ttime;
6171            }
6172
6173            public void incStartsLocked() {
6174                mStarts++;
6175            }
6176
6177            public void incNumCrashesLocked() {
6178                mNumCrashes++;
6179            }
6180
6181            public void incNumAnrsLocked() {
6182                mNumAnrs++;
6183            }
6184
6185            @Override
6186            public boolean isActive() {
6187                return mActive;
6188            }
6189
6190            @Override
6191            public long getUserTime(int which) {
6192                long val = mUserTime;
6193                if (which == STATS_CURRENT) {
6194                    val -= mLoadedUserTime;
6195                } else if (which == STATS_SINCE_UNPLUGGED) {
6196                    val -= mUnpluggedUserTime;
6197                }
6198                return val;
6199            }
6200
6201            @Override
6202            public long getSystemTime(int which) {
6203                long val = mSystemTime;
6204                if (which == STATS_CURRENT) {
6205                    val -= mLoadedSystemTime;
6206                } else if (which == STATS_SINCE_UNPLUGGED) {
6207                    val -= mUnpluggedSystemTime;
6208                }
6209                return val;
6210            }
6211
6212            @Override
6213            public long getForegroundTime(int which) {
6214                long val = mForegroundTime;
6215                if (which == STATS_CURRENT) {
6216                    val -= mLoadedForegroundTime;
6217                } else if (which == STATS_SINCE_UNPLUGGED) {
6218                    val -= mUnpluggedForegroundTime;
6219                }
6220                return val;
6221            }
6222
6223            @Override
6224            public int getStarts(int which) {
6225                int val = mStarts;
6226                if (which == STATS_CURRENT) {
6227                    val -= mLoadedStarts;
6228                } else if (which == STATS_SINCE_UNPLUGGED) {
6229                    val -= mUnpluggedStarts;
6230                }
6231                return val;
6232            }
6233
6234            @Override
6235            public int getNumCrashes(int which) {
6236                int val = mNumCrashes;
6237                if (which == STATS_CURRENT) {
6238                    val -= mLoadedNumCrashes;
6239                } else if (which == STATS_SINCE_UNPLUGGED) {
6240                    val -= mUnpluggedNumCrashes;
6241                }
6242                return val;
6243            }
6244
6245            @Override
6246            public int getNumAnrs(int which) {
6247                int val = mNumAnrs;
6248                if (which == STATS_CURRENT) {
6249                    val -= mLoadedNumAnrs;
6250                } else if (which == STATS_SINCE_UNPLUGGED) {
6251                    val -= mUnpluggedNumAnrs;
6252                }
6253                return val;
6254            }
6255        }
6256
6257        /**
6258         * The statistics associated with a particular package.
6259         */
6260        public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
6261            /**
6262             * Number of times wakeup alarms have occurred for this app.
6263             */
6264            ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
6265
6266            /**
6267             * The statics we have collected for this package's services.
6268             */
6269            final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
6270
6271            Pkg() {
6272                mOnBatteryScreenOffTimeBase.add(this);
6273            }
6274
6275            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
6276            }
6277
6278            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
6279            }
6280
6281            void detach() {
6282                mOnBatteryScreenOffTimeBase.remove(this);
6283            }
6284
6285            void readFromParcelLocked(Parcel in) {
6286                int numWA = in.readInt();
6287                mWakeupAlarms.clear();
6288                for (int i=0; i<numWA; i++) {
6289                    String tag = in.readString();
6290                    mWakeupAlarms.put(tag, new Counter(mOnBatteryTimeBase, in));
6291                }
6292
6293                int numServs = in.readInt();
6294                mServiceStats.clear();
6295                for (int m = 0; m < numServs; m++) {
6296                    String serviceName = in.readString();
6297                    Uid.Pkg.Serv serv = new Serv();
6298                    mServiceStats.put(serviceName, serv);
6299
6300                    serv.readFromParcelLocked(in);
6301                }
6302            }
6303
6304            void writeToParcelLocked(Parcel out) {
6305                int numWA = mWakeupAlarms.size();
6306                out.writeInt(numWA);
6307                for (int i=0; i<numWA; i++) {
6308                    out.writeString(mWakeupAlarms.keyAt(i));
6309                    mWakeupAlarms.valueAt(i).writeToParcel(out);
6310                }
6311
6312                final int NS = mServiceStats.size();
6313                out.writeInt(NS);
6314                for (int i=0; i<NS; i++) {
6315                    out.writeString(mServiceStats.keyAt(i));
6316                    Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
6317                    serv.writeToParcelLocked(out);
6318                }
6319            }
6320
6321            @Override
6322            public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
6323                return mWakeupAlarms;
6324            }
6325
6326            public void noteWakeupAlarmLocked(String tag) {
6327                Counter c = mWakeupAlarms.get(tag);
6328                if (c == null) {
6329                    c = new Counter(mOnBatteryTimeBase);
6330                    mWakeupAlarms.put(tag, c);
6331                }
6332                c.stepAtomic();
6333            }
6334
6335            @Override
6336            public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
6337                return mServiceStats;
6338            }
6339
6340            /**
6341             * The statistics associated with a particular service.
6342             */
6343            public final class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
6344                /**
6345                 * Total time (ms in battery uptime) the service has been left started.
6346                 */
6347                long mStartTime;
6348
6349                /**
6350                 * If service has been started and not yet stopped, this is
6351                 * when it was started.
6352                 */
6353                long mRunningSince;
6354
6355                /**
6356                 * True if we are currently running.
6357                 */
6358                boolean mRunning;
6359
6360                /**
6361                 * Total number of times startService() has been called.
6362                 */
6363                int mStarts;
6364
6365                /**
6366                 * Total time (ms in battery uptime) the service has been left launched.
6367                 */
6368                long mLaunchedTime;
6369
6370                /**
6371                 * If service has been launched and not yet exited, this is
6372                 * when it was launched (ms in battery uptime).
6373                 */
6374                long mLaunchedSince;
6375
6376                /**
6377                 * True if we are currently launched.
6378                 */
6379                boolean mLaunched;
6380
6381                /**
6382                 * Total number times the service has been launched.
6383                 */
6384                int mLaunches;
6385
6386                /**
6387                 * The amount of time spent started loaded from a previous save
6388                 * (ms in battery uptime).
6389                 */
6390                long mLoadedStartTime;
6391
6392                /**
6393                 * The number of starts loaded from a previous save.
6394                 */
6395                int mLoadedStarts;
6396
6397                /**
6398                 * The number of launches loaded from a previous save.
6399                 */
6400                int mLoadedLaunches;
6401
6402                /**
6403                 * The amount of time spent started as of the last run (ms
6404                 * in battery uptime).
6405                 */
6406                long mLastStartTime;
6407
6408                /**
6409                 * The number of starts as of the last run.
6410                 */
6411                int mLastStarts;
6412
6413                /**
6414                 * The number of launches as of the last run.
6415                 */
6416                int mLastLaunches;
6417
6418                /**
6419                 * The amount of time spent started when last unplugged (ms
6420                 * in battery uptime).
6421                 */
6422                long mUnpluggedStartTime;
6423
6424                /**
6425                 * The number of starts when last unplugged.
6426                 */
6427                int mUnpluggedStarts;
6428
6429                /**
6430                 * The number of launches when last unplugged.
6431                 */
6432                int mUnpluggedLaunches;
6433
6434                Serv() {
6435                    mOnBatteryTimeBase.add(this);
6436                }
6437
6438                public void onTimeStarted(long elapsedRealtime, long baseUptime,
6439                        long baseRealtime) {
6440                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
6441                    mUnpluggedStarts = mStarts;
6442                    mUnpluggedLaunches = mLaunches;
6443                }
6444
6445                public void onTimeStopped(long elapsedRealtime, long baseUptime,
6446                        long baseRealtime) {
6447                }
6448
6449                void detach() {
6450                    mOnBatteryTimeBase.remove(this);
6451                }
6452
6453                void readFromParcelLocked(Parcel in) {
6454                    mStartTime = in.readLong();
6455                    mRunningSince = in.readLong();
6456                    mRunning = in.readInt() != 0;
6457                    mStarts = in.readInt();
6458                    mLaunchedTime = in.readLong();
6459                    mLaunchedSince = in.readLong();
6460                    mLaunched = in.readInt() != 0;
6461                    mLaunches = in.readInt();
6462                    mLoadedStartTime = in.readLong();
6463                    mLoadedStarts = in.readInt();
6464                    mLoadedLaunches = in.readInt();
6465                    mLastStartTime = 0;
6466                    mLastStarts = 0;
6467                    mLastLaunches = 0;
6468                    mUnpluggedStartTime = in.readLong();
6469                    mUnpluggedStarts = in.readInt();
6470                    mUnpluggedLaunches = in.readInt();
6471                }
6472
6473                void writeToParcelLocked(Parcel out) {
6474                    out.writeLong(mStartTime);
6475                    out.writeLong(mRunningSince);
6476                    out.writeInt(mRunning ? 1 : 0);
6477                    out.writeInt(mStarts);
6478                    out.writeLong(mLaunchedTime);
6479                    out.writeLong(mLaunchedSince);
6480                    out.writeInt(mLaunched ? 1 : 0);
6481                    out.writeInt(mLaunches);
6482                    out.writeLong(mLoadedStartTime);
6483                    out.writeInt(mLoadedStarts);
6484                    out.writeInt(mLoadedLaunches);
6485                    out.writeLong(mUnpluggedStartTime);
6486                    out.writeInt(mUnpluggedStarts);
6487                    out.writeInt(mUnpluggedLaunches);
6488                }
6489
6490                long getLaunchTimeToNowLocked(long batteryUptime) {
6491                    if (!mLaunched) return mLaunchedTime;
6492                    return mLaunchedTime + batteryUptime - mLaunchedSince;
6493                }
6494
6495                long getStartTimeToNowLocked(long batteryUptime) {
6496                    if (!mRunning) return mStartTime;
6497                    return mStartTime + batteryUptime - mRunningSince;
6498                }
6499
6500                public void startLaunchedLocked() {
6501                    if (!mLaunched) {
6502                        mLaunches++;
6503                        mLaunchedSince = getBatteryUptimeLocked();
6504                        mLaunched = true;
6505                    }
6506                }
6507
6508                public void stopLaunchedLocked() {
6509                    if (mLaunched) {
6510                        long time = getBatteryUptimeLocked() - mLaunchedSince;
6511                        if (time > 0) {
6512                            mLaunchedTime += time;
6513                        } else {
6514                            mLaunches--;
6515                        }
6516                        mLaunched = false;
6517                    }
6518                }
6519
6520                public void startRunningLocked() {
6521                    if (!mRunning) {
6522                        mStarts++;
6523                        mRunningSince = getBatteryUptimeLocked();
6524                        mRunning = true;
6525                    }
6526                }
6527
6528                public void stopRunningLocked() {
6529                    if (mRunning) {
6530                        long time = getBatteryUptimeLocked() - mRunningSince;
6531                        if (time > 0) {
6532                            mStartTime += time;
6533                        } else {
6534                            mStarts--;
6535                        }
6536                        mRunning = false;
6537                    }
6538                }
6539
6540                public BatteryStatsImpl getBatteryStats() {
6541                    return BatteryStatsImpl.this;
6542                }
6543
6544                @Override
6545                public int getLaunches(int which) {
6546                    int val = mLaunches;
6547                    if (which == STATS_CURRENT) {
6548                        val -= mLoadedLaunches;
6549                    } else if (which == STATS_SINCE_UNPLUGGED) {
6550                        val -= mUnpluggedLaunches;
6551                    }
6552                    return val;
6553                }
6554
6555                @Override
6556                public long getStartTime(long now, int which) {
6557                    long val = getStartTimeToNowLocked(now);
6558                    if (which == STATS_CURRENT) {
6559                        val -= mLoadedStartTime;
6560                    } else if (which == STATS_SINCE_UNPLUGGED) {
6561                        val -= mUnpluggedStartTime;
6562                    }
6563                    return val;
6564                }
6565
6566                @Override
6567                public int getStarts(int which) {
6568                    int val = mStarts;
6569                    if (which == STATS_CURRENT) {
6570                        val -= mLoadedStarts;
6571                    } else if (which == STATS_SINCE_UNPLUGGED) {
6572                        val -= mUnpluggedStarts;
6573                    }
6574
6575                    return val;
6576                }
6577            }
6578
6579            final Serv newServiceStatsLocked() {
6580                return new Serv();
6581            }
6582        }
6583
6584        /**
6585         * Retrieve the statistics object for a particular process, creating
6586         * if needed.
6587         */
6588        public Proc getProcessStatsLocked(String name) {
6589            Proc ps = mProcessStats.get(name);
6590            if (ps == null) {
6591                ps = new Proc(name);
6592                mProcessStats.put(name, ps);
6593            }
6594
6595            return ps;
6596        }
6597
6598        public void updateProcessStateLocked(String procName, int state, long elapsedRealtimeMs) {
6599            int procState;
6600            if (state <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
6601                procState = PROCESS_STATE_FOREGROUND;
6602            } else if (state <= ActivityManager.PROCESS_STATE_RECEIVER) {
6603                procState = PROCESS_STATE_ACTIVE;
6604            } else {
6605                procState = PROCESS_STATE_RUNNING;
6606            }
6607            updateRealProcessStateLocked(procName, procState, elapsedRealtimeMs);
6608        }
6609
6610        public void updateRealProcessStateLocked(String procName, int procState,
6611                long elapsedRealtimeMs) {
6612            Proc proc = getProcessStatsLocked(procName);
6613            if (proc.mProcessState != procState) {
6614                boolean changed;
6615                if (procState < proc.mProcessState) {
6616                    // Has this process become more important?  If so,
6617                    // we may need to change the uid if the currrent uid proc state
6618                    // is not as important as what we are now setting.
6619                    changed = mProcessState > procState;
6620                } else {
6621                    // Has this process become less important?  If so,
6622                    // we may need to change the uid if the current uid proc state
6623                    // is the same importance as the old setting.
6624                    changed = mProcessState == proc.mProcessState;
6625                }
6626                proc.mProcessState = procState;
6627                if (changed) {
6628                    // uid's state may have changed; compute what the new state should be.
6629                    int uidProcState = PROCESS_STATE_NONE;
6630                    for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
6631                        proc = mProcessStats.valueAt(ip);
6632                        if (proc.mProcessState < uidProcState) {
6633                            uidProcState = proc.mProcessState;
6634                        }
6635                    }
6636                    updateUidProcessStateLocked(uidProcState, elapsedRealtimeMs);
6637                }
6638            }
6639        }
6640
6641        public SparseArray<? extends Pid> getPidStats() {
6642            return mPids;
6643        }
6644
6645        public Pid getPidStatsLocked(int pid) {
6646            Pid p = mPids.get(pid);
6647            if (p == null) {
6648                p = new Pid();
6649                mPids.put(pid, p);
6650            }
6651            return p;
6652        }
6653
6654        /**
6655         * Retrieve the statistics object for a particular service, creating
6656         * if needed.
6657         */
6658        public Pkg getPackageStatsLocked(String name) {
6659            Pkg ps = mPackageStats.get(name);
6660            if (ps == null) {
6661                ps = new Pkg();
6662                mPackageStats.put(name, ps);
6663            }
6664
6665            return ps;
6666        }
6667
6668        /**
6669         * Retrieve the statistics object for a particular service, creating
6670         * if needed.
6671         */
6672        public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
6673            Pkg ps = getPackageStatsLocked(pkg);
6674            Pkg.Serv ss = ps.mServiceStats.get(serv);
6675            if (ss == null) {
6676                ss = ps.newServiceStatsLocked();
6677                ps.mServiceStats.put(serv, ss);
6678            }
6679
6680            return ss;
6681        }
6682
6683        public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
6684            StopwatchTimer timer = mSyncStats.instantiateObject();
6685            timer.readSummaryFromParcelLocked(in);
6686            mSyncStats.add(name, timer);
6687        }
6688
6689        public void readJobSummaryFromParcelLocked(String name, Parcel in) {
6690            StopwatchTimer timer = mJobStats.instantiateObject();
6691            timer.readSummaryFromParcelLocked(in);
6692            mJobStats.add(name, timer);
6693        }
6694
6695        public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
6696            Wakelock wl = new Wakelock();
6697            mWakelockStats.add(wlName, wl);
6698            if (in.readInt() != 0) {
6699                wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
6700            }
6701            if (in.readInt() != 0) {
6702                wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
6703            }
6704            if (in.readInt() != 0) {
6705                wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
6706            }
6707            if (in.readInt() != 0) {
6708                wl.getStopwatchTimer(WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
6709            }
6710        }
6711
6712        public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
6713            Sensor se = mSensorStats.get(sensor);
6714            if (se == null) {
6715                if (!create) {
6716                    return null;
6717                }
6718                se = new Sensor(sensor);
6719                mSensorStats.put(sensor, se);
6720            }
6721            StopwatchTimer t = se.mTimer;
6722            if (t != null) {
6723                return t;
6724            }
6725            ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
6726            if (timers == null) {
6727                timers = new ArrayList<StopwatchTimer>();
6728                mSensorTimers.put(sensor, timers);
6729            }
6730            t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mOnBatteryTimeBase);
6731            se.mTimer = t;
6732            return t;
6733        }
6734
6735        public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
6736            StopwatchTimer t = mSyncStats.startObject(name);
6737            if (t != null) {
6738                t.startRunningLocked(elapsedRealtimeMs);
6739            }
6740        }
6741
6742        public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
6743            StopwatchTimer t = mSyncStats.stopObject(name);
6744            if (t != null) {
6745                t.stopRunningLocked(elapsedRealtimeMs);
6746            }
6747        }
6748
6749        public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
6750            StopwatchTimer t = mJobStats.startObject(name);
6751            if (t != null) {
6752                t.startRunningLocked(elapsedRealtimeMs);
6753            }
6754        }
6755
6756        public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
6757            StopwatchTimer t = mJobStats.stopObject(name);
6758            if (t != null) {
6759                t.stopRunningLocked(elapsedRealtimeMs);
6760            }
6761        }
6762
6763        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
6764            Wakelock wl = mWakelockStats.startObject(name);
6765            if (wl != null) {
6766                wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
6767            }
6768            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
6769                Pid p = getPidStatsLocked(pid);
6770                if (p.mWakeNesting++ == 0) {
6771                    p.mWakeStartMs = elapsedRealtimeMs;
6772                }
6773            }
6774        }
6775
6776        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
6777            Wakelock wl = mWakelockStats.stopObject(name);
6778            if (wl != null) {
6779                wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
6780            }
6781            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
6782                Pid p = mPids.get(pid);
6783                if (p != null && p.mWakeNesting > 0) {
6784                    if (p.mWakeNesting-- == 1) {
6785                        p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
6786                        p.mWakeStartMs = 0;
6787                    }
6788                }
6789            }
6790        }
6791
6792        public void reportExcessiveWakeLocked(String proc, long overTime, long usedTime) {
6793            Proc p = getProcessStatsLocked(proc);
6794            if (p != null) {
6795                p.addExcessiveWake(overTime, usedTime);
6796            }
6797        }
6798
6799        public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
6800            Proc p = getProcessStatsLocked(proc);
6801            if (p != null) {
6802                p.addExcessiveCpu(overTime, usedTime);
6803            }
6804        }
6805
6806        public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
6807            StopwatchTimer t = getSensorTimerLocked(sensor, true);
6808            if (t != null) {
6809                t.startRunningLocked(elapsedRealtimeMs);
6810            }
6811        }
6812
6813        public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
6814            // Don't create a timer if one doesn't already exist
6815            StopwatchTimer t = getSensorTimerLocked(sensor, false);
6816            if (t != null) {
6817                t.stopRunningLocked(elapsedRealtimeMs);
6818            }
6819        }
6820
6821        public void noteStartGps(long elapsedRealtimeMs) {
6822            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
6823            if (t != null) {
6824                t.startRunningLocked(elapsedRealtimeMs);
6825            }
6826        }
6827
6828        public void noteStopGps(long elapsedRealtimeMs) {
6829            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
6830            if (t != null) {
6831                t.stopRunningLocked(elapsedRealtimeMs);
6832            }
6833        }
6834
6835        public BatteryStatsImpl getBatteryStats() {
6836            return BatteryStatsImpl.this;
6837        }
6838    }
6839
6840    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
6841        if (systemDir != null) {
6842            mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
6843                    new File(systemDir, "batterystats.bin.tmp"));
6844        } else {
6845            mFile = null;
6846        }
6847        mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
6848        mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
6849        mExternalSync = externalSync;
6850        mHandler = new MyHandler(handler.getLooper());
6851        mStartCount++;
6852        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
6853        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
6854            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
6855        }
6856        mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase);
6857        mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
6858        mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
6859        mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase);
6860        mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
6861        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
6862            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
6863                    mOnBatteryTimeBase);
6864        }
6865        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase);
6866        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
6867            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null,
6868                    mOnBatteryTimeBase);
6869        }
6870        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
6871            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6872            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6873        }
6874        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
6875            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6876            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
6877        }
6878        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
6879        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
6880        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
6881        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
6882        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
6883        mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase);
6884        mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase);
6885        for (int i=0; i<NUM_WIFI_STATES; i++) {
6886            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mOnBatteryTimeBase);
6887        }
6888        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
6889            mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i, null, mOnBatteryTimeBase);
6890        }
6891        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
6892            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i, null,
6893                    mOnBatteryTimeBase);
6894        }
6895        mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
6896        mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
6897        mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
6898        mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase);
6899        mOnBattery = mOnBatteryInternal = false;
6900        long uptime = SystemClock.uptimeMillis() * 1000;
6901        long realtime = SystemClock.elapsedRealtime() * 1000;
6902        initTimes(uptime, realtime);
6903        mStartPlatformVersion = mEndPlatformVersion = Build.ID;
6904        mDischargeStartLevel = 0;
6905        mDischargeUnplugLevel = 0;
6906        mDischargePlugLevel = -1;
6907        mDischargeCurrentLevel = 0;
6908        mCurrentBatteryLevel = 0;
6909        initDischarge();
6910        clearHistoryLocked();
6911        updateDailyDeadlineLocked();
6912    }
6913
6914    public BatteryStatsImpl(Parcel p) {
6915        mFile = null;
6916        mCheckinFile = null;
6917        mDailyFile = null;
6918        mHandler = null;
6919        mExternalSync = null;
6920        clearHistoryLocked();
6921        readFromParcel(p);
6922    }
6923
6924    public void setPowerProfile(PowerProfile profile) {
6925        synchronized (this) {
6926            mPowerProfile = profile;
6927
6928            // We need to initialize the KernelCpuSpeedReaders to read from
6929            // the first cpu of each core. Once we have the PowerProfile, we have access to this
6930            // information.
6931            final int numClusters = mPowerProfile.getNumCpuClusters();
6932            mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
6933            int firstCpuOfCluster = 0;
6934            for (int i = 0; i < numClusters; i++) {
6935                final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
6936                mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
6937                        numSpeedSteps);
6938                firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
6939            }
6940        }
6941    }
6942
6943    public void setCallback(BatteryCallback cb) {
6944        mCallback = cb;
6945    }
6946
6947    public void setRadioScanningTimeout(long timeout) {
6948        if (mPhoneSignalScanningTimer != null) {
6949            mPhoneSignalScanningTimer.setTimeout(timeout);
6950        }
6951    }
6952
6953    public void updateDailyDeadlineLocked() {
6954        // Get the current time.
6955        long currentTime = mDailyStartTime = System.currentTimeMillis();
6956        Calendar calDeadline = Calendar.getInstance();
6957        calDeadline.setTimeInMillis(currentTime);
6958
6959        // Move time up to the next day, ranging from 1am to 3pm.
6960        calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
6961        calDeadline.set(Calendar.MILLISECOND, 0);
6962        calDeadline.set(Calendar.SECOND, 0);
6963        calDeadline.set(Calendar.MINUTE, 0);
6964        calDeadline.set(Calendar.HOUR_OF_DAY, 1);
6965        mNextMinDailyDeadline = calDeadline.getTimeInMillis();
6966        calDeadline.set(Calendar.HOUR_OF_DAY, 3);
6967        mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
6968    }
6969
6970    public void recordDailyStatsIfNeededLocked(boolean settled) {
6971        long currentTime = System.currentTimeMillis();
6972        if (currentTime >= mNextMaxDailyDeadline) {
6973            recordDailyStatsLocked();
6974        } else if (settled && currentTime >= mNextMinDailyDeadline) {
6975            recordDailyStatsLocked();
6976        } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
6977            recordDailyStatsLocked();
6978        }
6979    }
6980
6981    public void recordDailyStatsLocked() {
6982        DailyItem item = new DailyItem();
6983        item.mStartTime = mDailyStartTime;
6984        item.mEndTime = System.currentTimeMillis();
6985        boolean hasData = false;
6986        if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
6987            hasData = true;
6988            item.mDischargeSteps = new LevelStepTracker(
6989                    mDailyDischargeStepTracker.mNumStepDurations,
6990                    mDailyDischargeStepTracker.mStepDurations);
6991        }
6992        if (mDailyChargeStepTracker.mNumStepDurations > 0) {
6993            hasData = true;
6994            item.mChargeSteps = new LevelStepTracker(
6995                    mDailyChargeStepTracker.mNumStepDurations,
6996                    mDailyChargeStepTracker.mStepDurations);
6997        }
6998        if (mDailyPackageChanges != null) {
6999            hasData = true;
7000            item.mPackageChanges = mDailyPackageChanges;
7001            mDailyPackageChanges = null;
7002        }
7003        mDailyDischargeStepTracker.init();
7004        mDailyChargeStepTracker.init();
7005        updateDailyDeadlineLocked();
7006
7007        if (hasData) {
7008            mDailyItems.add(item);
7009            while (mDailyItems.size() > MAX_DAILY_ITEMS) {
7010                mDailyItems.remove(0);
7011            }
7012            final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
7013            try {
7014                XmlSerializer out = new FastXmlSerializer();
7015                out.setOutput(memStream, StandardCharsets.UTF_8.name());
7016                writeDailyItemsLocked(out);
7017                BackgroundThread.getHandler().post(new Runnable() {
7018                    @Override
7019                    public void run() {
7020                        synchronized (mCheckinFile) {
7021                            FileOutputStream stream = null;
7022                            try {
7023                                stream = mDailyFile.startWrite();
7024                                memStream.writeTo(stream);
7025                                stream.flush();
7026                                FileUtils.sync(stream);
7027                                stream.close();
7028                                mDailyFile.finishWrite(stream);
7029                            } catch (IOException e) {
7030                                Slog.w("BatteryStats",
7031                                        "Error writing battery daily items", e);
7032                                mDailyFile.failWrite(stream);
7033                            }
7034                        }
7035                    }
7036                });
7037            } catch (IOException e) {
7038            }
7039        }
7040    }
7041
7042    private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
7043        StringBuilder sb = new StringBuilder(64);
7044        out.startDocument(null, true);
7045        out.startTag(null, "daily-items");
7046        for (int i=0; i<mDailyItems.size(); i++) {
7047            final DailyItem dit = mDailyItems.get(i);
7048            out.startTag(null, "item");
7049            out.attribute(null, "start", Long.toString(dit.mStartTime));
7050            out.attribute(null, "end", Long.toString(dit.mEndTime));
7051            writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
7052            writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
7053            if (dit.mPackageChanges != null) {
7054                for (int j=0; j<dit.mPackageChanges.size(); j++) {
7055                    PackageChange pc = dit.mPackageChanges.get(j);
7056                    if (pc.mUpdate) {
7057                        out.startTag(null, "upd");
7058                        out.attribute(null, "pkg", pc.mPackageName);
7059                        out.attribute(null, "ver", Integer.toString(pc.mVersionCode));
7060                        out.endTag(null, "upd");
7061                    } else {
7062                        out.startTag(null, "rem");
7063                        out.attribute(null, "pkg", pc.mPackageName);
7064                        out.endTag(null, "rem");
7065                    }
7066                }
7067            }
7068            out.endTag(null, "item");
7069        }
7070        out.endTag(null, "daily-items");
7071        out.endDocument();
7072    }
7073
7074    private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
7075            StringBuilder tmpBuilder) throws IOException {
7076        if (steps != null) {
7077            out.startTag(null, tag);
7078            out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
7079            for (int i=0; i<steps.mNumStepDurations; i++) {
7080                out.startTag(null, "s");
7081                tmpBuilder.setLength(0);
7082                steps.encodeEntryAt(i, tmpBuilder);
7083                out.attribute(null, "v", tmpBuilder.toString());
7084                out.endTag(null, "s");
7085            }
7086            out.endTag(null, tag);
7087        }
7088    }
7089
7090    public void readDailyStatsLocked() {
7091        Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
7092        mDailyItems.clear();
7093        FileInputStream stream;
7094        try {
7095            stream = mDailyFile.openRead();
7096        } catch (FileNotFoundException e) {
7097            return;
7098        }
7099        try {
7100            XmlPullParser parser = Xml.newPullParser();
7101            parser.setInput(stream, StandardCharsets.UTF_8.name());
7102            readDailyItemsLocked(parser);
7103        } catch (XmlPullParserException e) {
7104        } finally {
7105            try {
7106                stream.close();
7107            } catch (IOException e) {
7108            }
7109        }
7110    }
7111
7112    private void readDailyItemsLocked(XmlPullParser parser) {
7113        try {
7114            int type;
7115            while ((type = parser.next()) != XmlPullParser.START_TAG
7116                    && type != XmlPullParser.END_DOCUMENT) {
7117                ;
7118            }
7119
7120            if (type != XmlPullParser.START_TAG) {
7121                throw new IllegalStateException("no start tag found");
7122            }
7123
7124            int outerDepth = parser.getDepth();
7125            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7126                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7127                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7128                    continue;
7129                }
7130
7131                String tagName = parser.getName();
7132                if (tagName.equals("item")) {
7133                    readDailyItemTagLocked(parser);
7134                } else {
7135                    Slog.w(TAG, "Unknown element under <daily-items>: "
7136                            + parser.getName());
7137                    XmlUtils.skipCurrentTag(parser);
7138                }
7139            }
7140
7141        } catch (IllegalStateException e) {
7142            Slog.w(TAG, "Failed parsing daily " + e);
7143        } catch (NullPointerException e) {
7144            Slog.w(TAG, "Failed parsing daily " + e);
7145        } catch (NumberFormatException e) {
7146            Slog.w(TAG, "Failed parsing daily " + e);
7147        } catch (XmlPullParserException e) {
7148            Slog.w(TAG, "Failed parsing daily " + e);
7149        } catch (IOException e) {
7150            Slog.w(TAG, "Failed parsing daily " + e);
7151        } catch (IndexOutOfBoundsException e) {
7152            Slog.w(TAG, "Failed parsing daily " + e);
7153        }
7154    }
7155
7156    void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
7157            XmlPullParserException, IOException {
7158        DailyItem dit = new DailyItem();
7159        String attr = parser.getAttributeValue(null, "start");
7160        if (attr != null) {
7161            dit.mStartTime = Long.parseLong(attr);
7162        }
7163        attr = parser.getAttributeValue(null, "end");
7164        if (attr != null) {
7165            dit.mEndTime = Long.parseLong(attr);
7166        }
7167        int outerDepth = parser.getDepth();
7168        int type;
7169        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7170                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7171            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7172                continue;
7173            }
7174
7175            String tagName = parser.getName();
7176            if (tagName.equals("dis")) {
7177                readDailyItemTagDetailsLocked(parser, dit, false, "dis");
7178            } else if (tagName.equals("chg")) {
7179                readDailyItemTagDetailsLocked(parser, dit, true, "chg");
7180            } else if (tagName.equals("upd")) {
7181                if (dit.mPackageChanges == null) {
7182                    dit.mPackageChanges = new ArrayList<>();
7183                }
7184                PackageChange pc = new PackageChange();
7185                pc.mUpdate = true;
7186                pc.mPackageName = parser.getAttributeValue(null, "pkg");
7187                String verStr = parser.getAttributeValue(null, "ver");
7188                pc.mVersionCode = verStr != null ? Integer.parseInt(verStr) : 0;
7189                dit.mPackageChanges.add(pc);
7190                XmlUtils.skipCurrentTag(parser);
7191            } else if (tagName.equals("rem")) {
7192                if (dit.mPackageChanges == null) {
7193                    dit.mPackageChanges = new ArrayList<>();
7194                }
7195                PackageChange pc = new PackageChange();
7196                pc.mUpdate = false;
7197                pc.mPackageName = parser.getAttributeValue(null, "pkg");
7198                dit.mPackageChanges.add(pc);
7199                XmlUtils.skipCurrentTag(parser);
7200            } else {
7201                Slog.w(TAG, "Unknown element under <item>: "
7202                        + parser.getName());
7203                XmlUtils.skipCurrentTag(parser);
7204            }
7205        }
7206        mDailyItems.add(dit);
7207    }
7208
7209    void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
7210            String tag)
7211            throws NumberFormatException, XmlPullParserException, IOException {
7212        final String numAttr = parser.getAttributeValue(null, "n");
7213        if (numAttr == null) {
7214            Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
7215            XmlUtils.skipCurrentTag(parser);
7216            return;
7217        }
7218        final int num = Integer.parseInt(numAttr);
7219        LevelStepTracker steps = new LevelStepTracker(num);
7220        if (isCharge) {
7221            dit.mChargeSteps = steps;
7222        } else {
7223            dit.mDischargeSteps = steps;
7224        }
7225        int i = 0;
7226        int outerDepth = parser.getDepth();
7227        int type;
7228        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7229                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7230            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7231                continue;
7232            }
7233
7234            String tagName = parser.getName();
7235            if ("s".equals(tagName)) {
7236                if (i < num) {
7237                    String valueAttr = parser.getAttributeValue(null, "v");
7238                    if (valueAttr != null) {
7239                        steps.decodeEntryAt(i, valueAttr);
7240                        i++;
7241                    }
7242                }
7243            } else {
7244                Slog.w(TAG, "Unknown element under <" + tag + ">: "
7245                        + parser.getName());
7246                XmlUtils.skipCurrentTag(parser);
7247            }
7248        }
7249        steps.mNumStepDurations = i;
7250    }
7251
7252    @Override
7253    public DailyItem getDailyItemLocked(int daysAgo) {
7254        int index = mDailyItems.size()-1-daysAgo;
7255        return index >= 0 ? mDailyItems.get(index) : null;
7256    }
7257
7258    @Override
7259    public long getCurrentDailyStartTime() {
7260        return mDailyStartTime;
7261    }
7262
7263    @Override
7264    public long getNextMinDailyDeadline() {
7265        return mNextMinDailyDeadline;
7266    }
7267
7268    @Override
7269    public long getNextMaxDailyDeadline() {
7270        return mNextMaxDailyDeadline;
7271    }
7272
7273    @Override
7274    public boolean startIteratingOldHistoryLocked() {
7275        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
7276                + " pos=" + mHistoryBuffer.dataPosition());
7277        if ((mHistoryIterator = mHistory) == null) {
7278            return false;
7279        }
7280        mHistoryBuffer.setDataPosition(0);
7281        mHistoryReadTmp.clear();
7282        mReadOverflow = false;
7283        mIteratingHistory = true;
7284        return true;
7285    }
7286
7287    @Override
7288    public boolean getNextOldHistoryLocked(HistoryItem out) {
7289        boolean end = mHistoryBuffer.dataPosition() >= mHistoryBuffer.dataSize();
7290        if (!end) {
7291            readHistoryDelta(mHistoryBuffer, mHistoryReadTmp);
7292            mReadOverflow |= mHistoryReadTmp.cmd == HistoryItem.CMD_OVERFLOW;
7293        }
7294        HistoryItem cur = mHistoryIterator;
7295        if (cur == null) {
7296            if (!mReadOverflow && !end) {
7297                Slog.w(TAG, "Old history ends before new history!");
7298            }
7299            return false;
7300        }
7301        out.setTo(cur);
7302        mHistoryIterator = cur.next;
7303        if (!mReadOverflow) {
7304            if (end) {
7305                Slog.w(TAG, "New history ends before old history!");
7306            } else if (!out.same(mHistoryReadTmp)) {
7307                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
7308                pw.println("Histories differ!");
7309                pw.println("Old history:");
7310                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
7311                pw.println("New history:");
7312                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
7313                        true);
7314                pw.flush();
7315            }
7316        }
7317        return true;
7318    }
7319
7320    @Override
7321    public void finishIteratingOldHistoryLocked() {
7322        mIteratingHistory = false;
7323        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
7324        mHistoryIterator = null;
7325    }
7326
7327    public int getHistoryTotalSize() {
7328        return MAX_HISTORY_BUFFER;
7329    }
7330
7331    public int getHistoryUsedSize() {
7332        return mHistoryBuffer.dataSize();
7333    }
7334
7335    @Override
7336    public boolean startIteratingHistoryLocked() {
7337        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
7338                + " pos=" + mHistoryBuffer.dataPosition());
7339        if (mHistoryBuffer.dataSize() <= 0) {
7340            return false;
7341        }
7342        mHistoryBuffer.setDataPosition(0);
7343        mReadOverflow = false;
7344        mIteratingHistory = true;
7345        mReadHistoryStrings = new String[mHistoryTagPool.size()];
7346        mReadHistoryUids = new int[mHistoryTagPool.size()];
7347        mReadHistoryChars = 0;
7348        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
7349            final HistoryTag tag = ent.getKey();
7350            final int idx = ent.getValue();
7351            mReadHistoryStrings[idx] = tag.string;
7352            mReadHistoryUids[idx] = tag.uid;
7353            mReadHistoryChars += tag.string.length() + 1;
7354        }
7355        return true;
7356    }
7357
7358    @Override
7359    public int getHistoryStringPoolSize() {
7360        return mReadHistoryStrings.length;
7361    }
7362
7363    @Override
7364    public int getHistoryStringPoolBytes() {
7365        // Each entry is a fixed 12 bytes: 4 for index, 4 for uid, 4 for string size
7366        // Each string character is 2 bytes.
7367        return (mReadHistoryStrings.length * 12) + (mReadHistoryChars * 2);
7368    }
7369
7370    @Override
7371    public String getHistoryTagPoolString(int index) {
7372        return mReadHistoryStrings[index];
7373    }
7374
7375    @Override
7376    public int getHistoryTagPoolUid(int index) {
7377        return mReadHistoryUids[index];
7378    }
7379
7380    @Override
7381    public boolean getNextHistoryLocked(HistoryItem out) {
7382        final int pos = mHistoryBuffer.dataPosition();
7383        if (pos == 0) {
7384            out.clear();
7385        }
7386        boolean end = pos >= mHistoryBuffer.dataSize();
7387        if (end) {
7388            return false;
7389        }
7390
7391        final long lastRealtime = out.time;
7392        final long lastWalltime = out.currentTime;
7393        readHistoryDelta(mHistoryBuffer, out);
7394        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
7395                && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
7396            out.currentTime = lastWalltime + (out.time - lastRealtime);
7397        }
7398        return true;
7399    }
7400
7401    @Override
7402    public void finishIteratingHistoryLocked() {
7403        mIteratingHistory = false;
7404        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
7405        mReadHistoryStrings = null;
7406    }
7407
7408    @Override
7409    public long getHistoryBaseTime() {
7410        return mHistoryBaseTime;
7411    }
7412
7413    @Override
7414    public int getStartCount() {
7415        return mStartCount;
7416    }
7417
7418    public boolean isOnBattery() {
7419        return mOnBattery;
7420    }
7421
7422    public boolean isCharging() {
7423        return mCharging;
7424    }
7425
7426    public boolean isScreenOn() {
7427        return mScreenState == Display.STATE_ON;
7428    }
7429
7430    void initTimes(long uptime, long realtime) {
7431        mStartClockTime = System.currentTimeMillis();
7432        mOnBatteryTimeBase.init(uptime, realtime);
7433        mOnBatteryScreenOffTimeBase.init(uptime, realtime);
7434        mRealtime = 0;
7435        mUptime = 0;
7436        mRealtimeStart = realtime;
7437        mUptimeStart = uptime;
7438    }
7439
7440    void initDischarge() {
7441        mLowDischargeAmountSinceCharge = 0;
7442        mHighDischargeAmountSinceCharge = 0;
7443        mDischargeAmountScreenOn = 0;
7444        mDischargeAmountScreenOnSinceCharge = 0;
7445        mDischargeAmountScreenOff = 0;
7446        mDischargeAmountScreenOffSinceCharge = 0;
7447        mDischargeStepTracker.init();
7448        mChargeStepTracker.init();
7449    }
7450
7451    public void resetAllStatsCmdLocked() {
7452        resetAllStatsLocked();
7453        final long mSecUptime = SystemClock.uptimeMillis();
7454        long uptime = mSecUptime * 1000;
7455        long mSecRealtime = SystemClock.elapsedRealtime();
7456        long realtime = mSecRealtime * 1000;
7457        mDischargeStartLevel = mHistoryCur.batteryLevel;
7458        pullPendingStateUpdatesLocked();
7459        addHistoryRecordLocked(mSecRealtime, mSecUptime);
7460        mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
7461                = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
7462        mOnBatteryTimeBase.reset(uptime, realtime);
7463        mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
7464        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
7465            if (mScreenState == Display.STATE_ON) {
7466                mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
7467                mDischargeScreenOffUnplugLevel = 0;
7468            } else {
7469                mDischargeScreenOnUnplugLevel = 0;
7470                mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
7471            }
7472            mDischargeAmountScreenOn = 0;
7473            mDischargeAmountScreenOff = 0;
7474        }
7475        initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
7476    }
7477
7478    private void resetAllStatsLocked() {
7479        mStartCount = 0;
7480        initTimes(SystemClock.uptimeMillis() * 1000, SystemClock.elapsedRealtime() * 1000);
7481        mScreenOnTimer.reset(false);
7482        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
7483            mScreenBrightnessTimer[i].reset(false);
7484        }
7485        mInteractiveTimer.reset(false);
7486        mPowerSaveModeEnabledTimer.reset(false);
7487        mDeviceIdleModeEnabledTimer.reset(false);
7488        mDeviceIdlingTimer.reset(false);
7489        mPhoneOnTimer.reset(false);
7490        mAudioOnTimer.reset(false);
7491        mVideoOnTimer.reset(false);
7492        mFlashlightOnTimer.reset(false);
7493        mCameraOnTimer.reset(false);
7494        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
7495            mPhoneSignalStrengthsTimer[i].reset(false);
7496        }
7497        mPhoneSignalScanningTimer.reset(false);
7498        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
7499            mPhoneDataConnectionsTimer[i].reset(false);
7500        }
7501        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
7502            mNetworkByteActivityCounters[i].reset(false);
7503            mNetworkPacketActivityCounters[i].reset(false);
7504        }
7505        mMobileRadioActiveTimer.reset(false);
7506        mMobileRadioActivePerAppTimer.reset(false);
7507        mMobileRadioActiveAdjustedTime.reset(false);
7508        mMobileRadioActiveUnknownTime.reset(false);
7509        mMobileRadioActiveUnknownCount.reset(false);
7510        mWifiOnTimer.reset(false);
7511        mGlobalWifiRunningTimer.reset(false);
7512        for (int i=0; i<NUM_WIFI_STATES; i++) {
7513            mWifiStateTimer[i].reset(false);
7514        }
7515        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
7516            mWifiSupplStateTimer[i].reset(false);
7517        }
7518        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
7519            mWifiSignalStrengthsTimer[i].reset(false);
7520        }
7521        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
7522            mBluetoothActivityCounters[i].reset(false);
7523            mWifiActivityCounters[i].reset(false);
7524        }
7525        mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
7526
7527        for (int i=0; i<mUidStats.size(); i++) {
7528            if (mUidStats.valueAt(i).reset()) {
7529                mUidStats.remove(mUidStats.keyAt(i));
7530                i--;
7531            }
7532        }
7533
7534        if (mKernelWakelockStats.size() > 0) {
7535            for (SamplingTimer timer : mKernelWakelockStats.values()) {
7536                mOnBatteryScreenOffTimeBase.remove(timer);
7537            }
7538            mKernelWakelockStats.clear();
7539        }
7540
7541        if (mWakeupReasonStats.size() > 0) {
7542            for (SamplingTimer timer : mWakeupReasonStats.values()) {
7543                mOnBatteryTimeBase.remove(timer);
7544            }
7545            mWakeupReasonStats.clear();
7546        }
7547
7548        mLastHistoryStepDetails = null;
7549        mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
7550        mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
7551        mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
7552        mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
7553        mLastStepStatUserTime = mCurStepStatUserTime = 0;
7554        mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
7555        mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
7556        mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
7557        mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
7558        mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
7559
7560        initDischarge();
7561
7562        clearHistoryLocked();
7563    }
7564
7565    private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
7566        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
7567            if (!mRecordAllHistory && i == HistoryItem.EVENT_PROC) {
7568                // Not recording process starts/stops.
7569                continue;
7570            }
7571            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
7572            if (active == null) {
7573                continue;
7574            }
7575            for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
7576                SparseIntArray uids = ent.getValue();
7577                for (int j=0; j<uids.size(); j++) {
7578                    addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
7579                            uids.keyAt(j));
7580                }
7581            }
7582        }
7583    }
7584
7585    void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
7586        if (oldScreenOn) {
7587            int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
7588            if (diff > 0) {
7589                mDischargeAmountScreenOn += diff;
7590                mDischargeAmountScreenOnSinceCharge += diff;
7591            }
7592        } else {
7593            int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
7594            if (diff > 0) {
7595                mDischargeAmountScreenOff += diff;
7596                mDischargeAmountScreenOffSinceCharge += diff;
7597            }
7598        }
7599        if (newScreenOn) {
7600            mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
7601            mDischargeScreenOffUnplugLevel = 0;
7602        } else {
7603            mDischargeScreenOnUnplugLevel = 0;
7604            mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
7605        }
7606    }
7607
7608    public void pullPendingStateUpdatesLocked() {
7609        if (mOnBatteryInternal) {
7610            final boolean screenOn = mScreenState == Display.STATE_ON;
7611            updateDischargeScreenLevelsLocked(screenOn, screenOn);
7612        }
7613    }
7614
7615    private String[] mMobileIfaces = EmptyArray.STRING;
7616    private String[] mWifiIfaces = EmptyArray.STRING;
7617
7618    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
7619
7620    private static final int NETWORK_STATS_LAST = 0;
7621    private static final int NETWORK_STATS_NEXT = 1;
7622    private static final int NETWORK_STATS_DELTA = 2;
7623
7624    private final NetworkStats[] mMobileNetworkStats = new NetworkStats[] {
7625            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7626            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7627            new NetworkStats(SystemClock.elapsedRealtime(), 50)
7628    };
7629
7630    private final NetworkStats[] mWifiNetworkStats = new NetworkStats[] {
7631            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7632            new NetworkStats(SystemClock.elapsedRealtime(), 50),
7633            new NetworkStats(SystemClock.elapsedRealtime(), 50)
7634    };
7635
7636    /**
7637     * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
7638     * as a buffer of NetworkStats objects to cycle through when computing deltas.
7639     */
7640    private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
7641                                                    NetworkStats[] networkStatsBuffer)
7642            throws IOException {
7643        if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
7644                false)) {
7645            return null;
7646        }
7647
7648        final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
7649                ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
7650        networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
7651                networkStatsBuffer[NETWORK_STATS_LAST], null, null,
7652                networkStatsBuffer[NETWORK_STATS_DELTA]);
7653        networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
7654        networkStatsBuffer[NETWORK_STATS_LAST] = stats;
7655        return networkStatsBuffer[NETWORK_STATS_DELTA];
7656    }
7657
7658    /**
7659     * Distribute WiFi energy info and network traffic to apps.
7660     * @param info The energy information from the WiFi controller.
7661     */
7662    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
7663        if (DEBUG_ENERGY) {
7664            Slog.d(TAG, "Updating wifi stats");
7665        }
7666
7667        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
7668        NetworkStats delta = null;
7669        try {
7670            if (!ArrayUtils.isEmpty(mWifiIfaces)) {
7671                delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
7672            }
7673        } catch (IOException e) {
7674            Slog.wtf(TAG, "Failed to get wifi network stats", e);
7675            return;
7676        }
7677
7678        if (!mOnBatteryInternal) {
7679            return;
7680        }
7681
7682        SparseLongArray rxPackets = new SparseLongArray();
7683        SparseLongArray txPackets = new SparseLongArray();
7684        long totalTxPackets = 0;
7685        long totalRxPackets = 0;
7686        if (delta != null) {
7687            final int size = delta.size();
7688            for (int i = 0; i < size; i++) {
7689                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
7690
7691                if (DEBUG_ENERGY) {
7692                    Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
7693                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
7694                            + " txPackets=" + entry.txPackets);
7695                }
7696
7697                if (entry.rxBytes == 0 || entry.txBytes == 0) {
7698                    continue;
7699                }
7700
7701                final Uid u = getUidStatsLocked(mapUid(entry.uid));
7702                u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
7703                        entry.rxPackets);
7704                u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
7705                        entry.txPackets);
7706                rxPackets.put(u.getUid(), entry.rxPackets);
7707                txPackets.put(u.getUid(), entry.txPackets);
7708
7709                // Sum the total number of packets so that the Rx Power and Tx Power can
7710                // be evenly distributed amongst the apps.
7711                totalRxPackets += entry.rxPackets;
7712                totalTxPackets += entry.txPackets;
7713
7714                mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
7715                        entry.rxBytes);
7716                mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
7717                        entry.txBytes);
7718                mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
7719                        entry.rxPackets);
7720                mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
7721                        entry.txPackets);
7722            }
7723        }
7724
7725        if (info != null) {
7726            mHasWifiEnergyReporting = true;
7727
7728            // Measured in mAms
7729            final long txTimeMs = info.getControllerTxTimeMillis();
7730            final long rxTimeMs = info.getControllerRxTimeMillis();
7731            final long idleTimeMs = info.getControllerIdleTimeMillis();
7732            final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
7733
7734            long leftOverRxTimeMs = rxTimeMs;
7735            long leftOverTxTimeMs = txTimeMs;
7736
7737            if (DEBUG_ENERGY) {
7738                Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
7739                Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
7740                Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
7741                Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
7742                Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
7743            }
7744
7745            long totalWifiLockTimeMs = 0;
7746            long totalScanTimeMs = 0;
7747
7748            // On the first pass, collect some totals so that we can normalize power
7749            // calculations if we need to.
7750            final int uidStatsSize = mUidStats.size();
7751            for (int i = 0; i < uidStatsSize; i++) {
7752                final Uid uid = mUidStats.valueAt(i);
7753
7754                // Sum the total scan power for all apps.
7755                totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
7756                        elapsedRealtimeMs * 1000) / 1000;
7757
7758                // Sum the total time holding wifi lock for all apps.
7759                totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
7760                        elapsedRealtimeMs * 1000) / 1000;
7761            }
7762
7763            if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
7764                Slog.d(TAG, "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
7765                        + rxTimeMs + " ms). Normalizing scan time.");
7766            }
7767            if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
7768                Slog.d(TAG, "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
7769                        + txTimeMs + " ms). Normalizing scan time.");
7770            }
7771
7772            // Actually assign and distribute power usage to apps.
7773            for (int i = 0; i < uidStatsSize; i++) {
7774                final Uid uid = mUidStats.valueAt(i);
7775
7776                long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
7777                        elapsedRealtimeMs * 1000) / 1000;
7778                if (scanTimeSinceMarkMs > 0) {
7779                    // Set the new mark so that next time we get new data since this point.
7780                    uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
7781
7782                    long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
7783                    long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
7784
7785                    // Our total scan time is more than the reported Tx/Rx time.
7786                    // This is possible because the cost of a scan is approximate.
7787                    // Let's normalize the result so that we evenly blame each app
7788                    // scanning.
7789                    //
7790                    // This means that we may have apps that transmitted/received packets not be
7791                    // blamed for this, but this is fine as scans are relatively more expensive.
7792                    if (totalScanTimeMs > rxTimeMs) {
7793                        scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
7794                                totalScanTimeMs;
7795                    }
7796                    if (totalScanTimeMs > txTimeMs) {
7797                        scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
7798                                totalScanTimeMs;
7799                    }
7800
7801                    if (DEBUG_ENERGY) {
7802                        Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
7803                                + scanRxTimeSinceMarkMs + " ms  Tx:"
7804                                + scanTxTimeSinceMarkMs + " ms)");
7805                    }
7806                    uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, scanRxTimeSinceMarkMs);
7807                    uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, scanTxTimeSinceMarkMs);
7808                    leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
7809                    leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
7810                }
7811
7812                // Distribute evenly the power consumed while Idle to each app holding a WiFi
7813                // lock.
7814                final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
7815                        elapsedRealtimeMs * 1000) / 1000;
7816                if (wifiLockTimeSinceMarkMs > 0) {
7817                    // Set the new mark so that next time we get new data since this point.
7818                    uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
7819
7820                    final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
7821                            / totalWifiLockTimeMs;
7822                    if (DEBUG_ENERGY) {
7823                        Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
7824                                + myIdleTimeMs + " ms");
7825                    }
7826                    uid.noteWifiControllerActivityLocked(CONTROLLER_IDLE_TIME, myIdleTimeMs);
7827                }
7828            }
7829
7830            if (DEBUG_ENERGY) {
7831                Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
7832                Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
7833            }
7834
7835            // Distribute the remaining Tx power appropriately between all apps that transmitted
7836            // packets.
7837            for (int i = 0; i < txPackets.size(); i++) {
7838                final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
7839                final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets;
7840                if (DEBUG_ENERGY) {
7841                    Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
7842                }
7843                uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, myTxTimeMs);
7844            }
7845
7846            // Distribute the remaining Rx power appropriately between all apps that received
7847            // packets.
7848            for (int i = 0; i < rxPackets.size(); i++) {
7849                final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
7850                final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
7851                if (DEBUG_ENERGY) {
7852                    Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
7853                }
7854                uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, myRxTimeMs);
7855            }
7856
7857            // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
7858
7859            // Update WiFi controller stats.
7860            mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
7861                    info.getControllerRxTimeMillis());
7862            mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
7863                    info.getControllerTxTimeMillis());
7864            mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
7865                    info.getControllerIdleTimeMillis());
7866
7867            // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
7868            final double opVolt = mPowerProfile.getAveragePower(
7869                    PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
7870            if (opVolt != 0) {
7871                // We store the power drain as mAms.
7872                mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
7873                        (long)(info.getControllerEnergyUsed() / opVolt));
7874            }
7875        }
7876    }
7877
7878    /**
7879     * Distribute Cell radio energy info and network traffic to apps.
7880     */
7881    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
7882        if (DEBUG_ENERGY) {
7883            Slog.d(TAG, "Updating mobile radio stats");
7884        }
7885
7886        NetworkStats delta = null;
7887        try {
7888            if (!ArrayUtils.isEmpty(mMobileIfaces)) {
7889                delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
7890            }
7891        } catch (IOException e) {
7892            Slog.wtf(TAG, "Failed to get mobile network stats", e);
7893            return;
7894        }
7895
7896        if (delta == null || !mOnBatteryInternal) {
7897            return;
7898        }
7899
7900        long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
7901                elapsedRealtimeMs * 1000);
7902        mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
7903        long totalPackets = delta.getTotalPackets();
7904
7905        final int size = delta.size();
7906        for (int i = 0; i < size; i++) {
7907            final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
7908
7909            if (entry.rxBytes == 0 || entry.txBytes == 0) {
7910                continue;
7911            }
7912
7913            if (DEBUG_ENERGY) {
7914                Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
7915                        + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
7916                        + " txPackets=" + entry.txPackets);
7917            }
7918
7919            final Uid u = getUidStatsLocked(mapUid(entry.uid));
7920            u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
7921                    entry.rxPackets);
7922            u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
7923                    entry.txPackets);
7924
7925            if (radioTime > 0) {
7926                // Distribute total radio active time in to this app.
7927                long appPackets = entry.rxPackets + entry.txPackets;
7928                long appRadioTime = (radioTime*appPackets)/totalPackets;
7929                u.noteMobileRadioActiveTimeLocked(appRadioTime);
7930                // Remove this app from the totals, so that we don't lose any time
7931                // due to rounding.
7932                radioTime -= appRadioTime;
7933                totalPackets -= appPackets;
7934            }
7935
7936            mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
7937                    entry.rxBytes);
7938            mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
7939                    entry.txBytes);
7940            mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
7941                    entry.rxPackets);
7942            mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
7943                    entry.txPackets);
7944        }
7945
7946        if (radioTime > 0) {
7947            // Whoops, there is some radio time we can't blame on an app!
7948            mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
7949            mMobileRadioActiveUnknownCount.addCountLocked(1);
7950        }
7951    }
7952
7953    /**
7954     * Distribute Bluetooth energy info and network traffic to apps.
7955     * @param info The energy information from the bluetooth controller.
7956     */
7957    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
7958        if (DEBUG_ENERGY) {
7959            Slog.d(TAG, "Updating bluetooth stats");
7960        }
7961
7962        if (info != null && mOnBatteryInternal) {
7963            mHasBluetoothEnergyReporting = true;
7964            mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
7965                    info.getControllerRxTimeMillis());
7966            mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
7967                    info.getControllerTxTimeMillis());
7968            mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
7969                    info.getControllerIdleTimeMillis());
7970
7971            // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
7972            final double opVolt = mPowerProfile.getAveragePower(
7973                    PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
7974            if (opVolt != 0) {
7975                // We store the power drain as mAms.
7976                mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
7977                        (long) (info.getControllerEnergyUsed() / opVolt));
7978            }
7979        }
7980    }
7981
7982    /**
7983     * Read and distribute kernel wake lock use across apps.
7984     */
7985    public void updateKernelWakelocksLocked() {
7986        final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
7987                mTmpWakelockStats);
7988        if (wakelockStats == null) {
7989            // Not crashing might make board bringup easier.
7990            Slog.w(TAG, "Couldn't get kernel wake lock stats");
7991            return;
7992        }
7993
7994        // Record whether we've seen a non-zero time (for debugging b/22716723).
7995        boolean seenNonZeroTime = false;
7996        for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
7997            String name = ent.getKey();
7998            KernelWakelockStats.Entry kws = ent.getValue();
7999
8000            SamplingTimer kwlt = mKernelWakelockStats.get(name);
8001            if (kwlt == null) {
8002                kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
8003                        true /* track reported val */);
8004                mKernelWakelockStats.put(name, kwlt);
8005            }
8006            kwlt.updateCurrentReportedCount(kws.mCount);
8007            kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
8008            kwlt.setUpdateVersion(kws.mVersion);
8009
8010            if (kws.mVersion != wakelockStats.kernelWakelockVersion)
8011            seenNonZeroTime |= kws.mTotalTime > 0;
8012        }
8013
8014        int numWakelocksSetStale = 0;
8015        if (wakelockStats.size() != mKernelWakelockStats.size()) {
8016            // Set timers to stale if they didn't appear in /proc/wakelocks this time.
8017            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
8018                SamplingTimer st = ent.getValue();
8019                if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
8020                    st.setStale();
8021                    numWakelocksSetStale++;
8022                }
8023            }
8024        }
8025
8026        if (!seenNonZeroTime) {
8027            Slog.wtf(TAG, "All kernel wakelocks had time of zero");
8028        }
8029
8030        if (numWakelocksSetStale == mKernelWakelockStats.size()) {
8031            Slog.wtf(TAG, "All kernel wakelocks were set stale. new version=" +
8032                    wakelockStats.kernelWakelockVersion);
8033        }
8034    }
8035
8036    // We use an anonymous class to access these variables,
8037    // so they can't live on the stack or they'd have to be
8038    // final MutableLong objects (more allocations).
8039    // Used in updateCpuTimeLocked().
8040    long mTempTotalCpuUserTimeUs;
8041    long mTempTotalCpuSystemTimeUs;
8042
8043    /**
8044     * Read and distribute CPU usage across apps. If their are partial wakelocks being held
8045     * and we are on battery with screen off, we give more of the cpu time to those apps holding
8046     * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
8047     */
8048    public void updateCpuTimeLocked() {
8049        if (mPowerProfile == null) {
8050            return;
8051        }
8052
8053        if (DEBUG_ENERGY_CPU) {
8054            Slog.d(TAG, "!Cpu updating!");
8055        }
8056
8057        // Holding a wakelock costs more than just using the cpu.
8058        // Currently, we assign only half the cpu time to an app that is running but
8059        // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
8060        // If no app is holding a wakelock, then the distribution is normal.
8061        final int wakelockWeight = 50;
8062
8063        // Read the time spent for each cluster at various cpu frequencies.
8064        final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
8065        for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
8066            clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
8067        }
8068
8069        int numWakelocks = 0;
8070
8071        // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
8072        // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
8073        final int numPartialTimers = mPartialTimers.size();
8074        if (mOnBatteryScreenOffTimeBase.isRunning()) {
8075            for (int i = 0; i < numPartialTimers; i++) {
8076                final StopwatchTimer timer = mPartialTimers.get(i);
8077                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
8078                    // Since the collection and blaming of wakelocks can be scheduled to run after
8079                    // some delay, the mPartialTimers list may have new entries. We can't blame
8080                    // the newly added timer for past cpu time, so we only consider timers that
8081                    // were present for one round of collection. Once a timer has gone through
8082                    // a round of collection, its mInList field is set to true.
8083                    numWakelocks++;
8084                }
8085            }
8086        }
8087
8088        final int numWakelocksF = numWakelocks;
8089        mTempTotalCpuUserTimeUs = 0;
8090        mTempTotalCpuSystemTimeUs = 0;
8091
8092        // Read the CPU data for each UID. This will internally generate a snapshot so next time
8093        // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
8094        // we just ignore the data.
8095        final long startTimeMs = SystemClock.elapsedRealtime();
8096        mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
8097                new KernelUidCpuTimeReader.Callback() {
8098                    @Override
8099                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
8100                                             long powerMaUs) {
8101                        final Uid u = getUidStatsLocked(mapUid(uid));
8102
8103                        // Accumulate the total system and user time.
8104                        mTempTotalCpuUserTimeUs += userTimeUs;
8105                        mTempTotalCpuSystemTimeUs += systemTimeUs;
8106
8107                        StringBuilder sb = null;
8108                        if (DEBUG_ENERGY_CPU) {
8109                            sb = new StringBuilder();
8110                            sb.append("  got time for uid=").append(u.mUid).append(": u=");
8111                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
8112                            sb.append(" s=");
8113                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
8114                            sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
8115                        }
8116
8117                        if (numWakelocksF > 0) {
8118                            // We have wakelocks being held, so only give a portion of the
8119                            // time to the process. The rest will be distributed among wakelock
8120                            // holders.
8121                            userTimeUs = (userTimeUs * wakelockWeight) / 100;
8122                            systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
8123                        }
8124
8125                        if (sb != null) {
8126                            sb.append("  adding to uid=").append(u.mUid).append(": u=");
8127                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
8128                            sb.append(" s=");
8129                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
8130                            sb.append(" p=").append(powerMaUs / 1000).append("mAms");
8131                            Slog.d(TAG, sb.toString());
8132                        }
8133
8134                        u.mUserCpuTime.addCountLocked(userTimeUs);
8135                        u.mSystemCpuTime.addCountLocked(systemTimeUs);
8136                        u.mCpuPower.addCountLocked(powerMaUs);
8137
8138                        // Add the cpu speeds to this UID. These are used as a ratio
8139                        // for computing the power this UID used.
8140                        final int numClusters = mPowerProfile.getNumCpuClusters();
8141                        if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
8142                                numClusters) {
8143                            u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
8144                        }
8145
8146                        for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
8147                            final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(
8148                                    cluster);
8149                            if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
8150                                    u.mCpuClusterSpeed[cluster].length) {
8151                                u.mCpuClusterSpeed[cluster] =
8152                                        new LongSamplingCounter[speedsInCluster];
8153                            }
8154
8155                            final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
8156                            for (int speed = 0; speed < clusterSpeeds[cluster].length; speed++) {
8157                                if (cpuSpeeds[speed] == null) {
8158                                    cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
8159                                }
8160                                cpuSpeeds[speed].addCountLocked(clusterSpeeds[cluster][speed]);
8161                            }
8162                        }
8163                    }
8164                });
8165
8166        if (DEBUG_ENERGY_CPU) {
8167            Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) +
8168                    " ms");
8169        }
8170
8171        if (mOnBatteryInternal && numWakelocks > 0) {
8172            // Distribute a portion of the total cpu time to wakelock holders.
8173            mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
8174            mTempTotalCpuSystemTimeUs =
8175                    (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
8176
8177            for (int i = 0; i < numPartialTimers; i++) {
8178                final StopwatchTimer timer = mPartialTimers.get(i);
8179
8180                // The system does not share any blame, as it is usually holding the wakelock
8181                // on behalf of an app.
8182                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
8183                    int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
8184                    int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
8185
8186                    if (DEBUG_ENERGY_CPU) {
8187                        StringBuilder sb = new StringBuilder();
8188                        sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
8189                                .append(": u=");
8190                        TimeUtils.formatDuration(userTimeUs / 1000, sb);
8191                        sb.append(" s=");
8192                        TimeUtils.formatDuration(systemTimeUs / 1000, sb);
8193                        Slog.d(TAG, sb.toString());
8194                    }
8195
8196                    timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
8197                    timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
8198
8199                    final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
8200                    proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
8201
8202                    mTempTotalCpuUserTimeUs -= userTimeUs;
8203                    mTempTotalCpuSystemTimeUs -= systemTimeUs;
8204                    numWakelocks--;
8205                }
8206            }
8207
8208            if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
8209                // Anything left over is given to the system.
8210                if (DEBUG_ENERGY_CPU) {
8211                    StringBuilder sb = new StringBuilder();
8212                    sb.append("  Distributing lost time to system: u=");
8213                    TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
8214                    sb.append(" s=");
8215                    TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
8216                    Slog.d(TAG, sb.toString());
8217                }
8218
8219                final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
8220                u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
8221                u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
8222
8223                final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
8224                proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000,
8225                        (int) mTempTotalCpuSystemTimeUs / 1000);
8226            }
8227        }
8228
8229        // See if there is a difference in wakelocks between this collection and the last
8230        // collection.
8231        if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
8232            // No difference, so each timer is now considered for the next collection.
8233            for (int i = 0; i < numPartialTimers; i++) {
8234                mPartialTimers.get(i).mInList = true;
8235            }
8236        } else {
8237            // The lists are different, meaning we added (or removed a timer) since the last
8238            // collection.
8239            final int numLastPartialTimers = mLastPartialTimers.size();
8240            for (int i = 0; i < numLastPartialTimers; i++) {
8241                mLastPartialTimers.get(i).mInList = false;
8242            }
8243            mLastPartialTimers.clear();
8244
8245            // Mark the current timers as gone through a collection.
8246            for (int i = 0; i < numPartialTimers; i++) {
8247                final StopwatchTimer timer = mPartialTimers.get(i);
8248                timer.mInList = true;
8249                mLastPartialTimers.add(timer);
8250            }
8251        }
8252    }
8253
8254    boolean setChargingLocked(boolean charging) {
8255        if (mCharging != charging) {
8256            mCharging = charging;
8257            if (charging) {
8258                mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
8259            } else {
8260                mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
8261            }
8262            mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
8263            return true;
8264        }
8265        return false;
8266    }
8267
8268    void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
8269            final int oldStatus, final int level) {
8270        boolean doWrite = false;
8271        Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
8272        m.arg1 = onBattery ? 1 : 0;
8273        mHandler.sendMessage(m);
8274
8275        final long uptime = mSecUptime * 1000;
8276        final long realtime = mSecRealtime * 1000;
8277        final boolean screenOn = mScreenState == Display.STATE_ON;
8278        if (onBattery) {
8279            // We will reset our status if we are unplugging after the
8280            // battery was last full, or the level is at 100, or
8281            // we have gone through a significant charge (from a very low
8282            // level to a now very high level).
8283            boolean reset = false;
8284            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
8285                    || level >= 90
8286                    || (mDischargeCurrentLevel < 20 && level >= 80)
8287                    || (getHighDischargeAmountSinceCharge() >= 200
8288                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
8289                Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
8290                        + " dischargeLevel=" + mDischargeCurrentLevel
8291                        + " lowAmount=" + getLowDischargeAmountSinceCharge()
8292                        + " highAmount=" + getHighDischargeAmountSinceCharge());
8293                // Before we write, collect a snapshot of the final aggregated
8294                // stats to be reported in the next checkin.  Only do this if we have
8295                // a sufficient amount of data to make it interesting.
8296                if (getLowDischargeAmountSinceCharge() >= 20) {
8297                    final Parcel parcel = Parcel.obtain();
8298                    writeSummaryToParcel(parcel, true);
8299                    BackgroundThread.getHandler().post(new Runnable() {
8300                        @Override public void run() {
8301                            synchronized (mCheckinFile) {
8302                                FileOutputStream stream = null;
8303                                try {
8304                                    stream = mCheckinFile.startWrite();
8305                                    stream.write(parcel.marshall());
8306                                    stream.flush();
8307                                    FileUtils.sync(stream);
8308                                    stream.close();
8309                                    mCheckinFile.finishWrite(stream);
8310                                } catch (IOException e) {
8311                                    Slog.w("BatteryStats",
8312                                            "Error writing checkin battery statistics", e);
8313                                    mCheckinFile.failWrite(stream);
8314                                } finally {
8315                                    parcel.recycle();
8316                                }
8317                            }
8318                        }
8319                    });
8320                }
8321                doWrite = true;
8322                resetAllStatsLocked();
8323                mDischargeStartLevel = level;
8324                reset = true;
8325                mDischargeStepTracker.init();
8326            }
8327            if (mCharging) {
8328                setChargingLocked(false);
8329            }
8330            mLastChargingStateLevel = level;
8331            mOnBattery = mOnBatteryInternal = true;
8332            mLastDischargeStepLevel = level;
8333            mMinDischargeStepLevel = level;
8334            mDischargeStepTracker.clearTime();
8335            mDailyDischargeStepTracker.clearTime();
8336            mInitStepMode = mCurStepMode;
8337            mModStepMode = 0;
8338            pullPendingStateUpdatesLocked();
8339            mHistoryCur.batteryLevel = (byte)level;
8340            mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8341            if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
8342                    + Integer.toHexString(mHistoryCur.states));
8343            if (reset) {
8344                mRecordingHistory = true;
8345                startRecordingHistory(mSecRealtime, mSecUptime, reset);
8346            }
8347            addHistoryRecordLocked(mSecRealtime, mSecUptime);
8348            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
8349            if (screenOn) {
8350                mDischargeScreenOnUnplugLevel = level;
8351                mDischargeScreenOffUnplugLevel = 0;
8352            } else {
8353                mDischargeScreenOnUnplugLevel = 0;
8354                mDischargeScreenOffUnplugLevel = level;
8355            }
8356            mDischargeAmountScreenOn = 0;
8357            mDischargeAmountScreenOff = 0;
8358            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
8359        } else {
8360            mLastChargingStateLevel = level;
8361            mOnBattery = mOnBatteryInternal = false;
8362            pullPendingStateUpdatesLocked();
8363            mHistoryCur.batteryLevel = (byte)level;
8364            mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8365            if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
8366                    + Integer.toHexString(mHistoryCur.states));
8367            addHistoryRecordLocked(mSecRealtime, mSecUptime);
8368            mDischargeCurrentLevel = mDischargePlugLevel = level;
8369            if (level < mDischargeUnplugLevel) {
8370                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
8371                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
8372            }
8373            updateDischargeScreenLevelsLocked(screenOn, screenOn);
8374            updateTimeBasesLocked(false, !screenOn, uptime, realtime);
8375            mChargeStepTracker.init();
8376            mLastChargeStepLevel = level;
8377            mMaxChargeStepLevel = level;
8378            mInitStepMode = mCurStepMode;
8379            mModStepMode = 0;
8380        }
8381        if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
8382            if (mFile != null) {
8383                writeAsyncLocked();
8384            }
8385        }
8386    }
8387
8388    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
8389            boolean reset) {
8390        mRecordingHistory = true;
8391        mHistoryCur.currentTime = System.currentTimeMillis();
8392        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
8393                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
8394                mHistoryCur);
8395        mHistoryCur.currentTime = 0;
8396        if (reset) {
8397            initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
8398        }
8399    }
8400
8401    private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
8402            final long uptimeMs) {
8403        if (mRecordingHistory) {
8404            mHistoryCur.currentTime = currentTime;
8405            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
8406                    mHistoryCur);
8407            mHistoryCur.currentTime = 0;
8408        }
8409    }
8410
8411    private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) {
8412        if (mRecordingHistory) {
8413            mHistoryCur.currentTime = System.currentTimeMillis();
8414            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_SHUTDOWN,
8415                    mHistoryCur);
8416            mHistoryCur.currentTime = 0;
8417        }
8418    }
8419
8420    private void scheduleSyncExternalStatsLocked(String reason) {
8421        if (mExternalSync != null) {
8422            mExternalSync.scheduleSync(reason);
8423        }
8424    }
8425
8426    private void scheduleSyncExternalWifiStatsLocked(String reason) {
8427        if (mExternalSync != null) {
8428            mExternalSync.scheduleWifiSync(reason);
8429        }
8430    }
8431
8432    // This should probably be exposed in the API, though it's not critical
8433    public static final int BATTERY_PLUGGED_NONE = 0;
8434
8435    public void setBatteryStateLocked(int status, int health, int plugType, int level,
8436            int temp, int volt) {
8437        final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
8438        final long uptime = SystemClock.uptimeMillis();
8439        final long elapsedRealtime = SystemClock.elapsedRealtime();
8440        if (!mHaveBatteryLevel) {
8441            mHaveBatteryLevel = true;
8442            // We start out assuming that the device is plugged in (not
8443            // on battery).  If our first report is now that we are indeed
8444            // plugged in, then twiddle our state to correctly reflect that
8445            // since we won't be going through the full setOnBattery().
8446            if (onBattery == mOnBattery) {
8447                if (onBattery) {
8448                    mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8449                } else {
8450                    mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
8451                }
8452            }
8453            // Always start out assuming charging, that will be updated later.
8454            mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
8455            mHistoryCur.batteryStatus = (byte)status;
8456            mHistoryCur.batteryLevel = (byte)level;
8457            mMaxChargeStepLevel = mMinDischargeStepLevel =
8458                    mLastChargeStepLevel = mLastDischargeStepLevel = level;
8459            mLastChargingStateLevel = level;
8460        } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
8461            recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
8462        }
8463        int oldStatus = mHistoryCur.batteryStatus;
8464        if (onBattery) {
8465            mDischargeCurrentLevel = level;
8466            if (!mRecordingHistory) {
8467                mRecordingHistory = true;
8468                startRecordingHistory(elapsedRealtime, uptime, true);
8469            }
8470        } else if (level < 96) {
8471            if (!mRecordingHistory) {
8472                mRecordingHistory = true;
8473                startRecordingHistory(elapsedRealtime, uptime, true);
8474            }
8475        }
8476        mCurrentBatteryLevel = level;
8477        if (mDischargePlugLevel < 0) {
8478            mDischargePlugLevel = level;
8479        }
8480        if (onBattery != mOnBattery) {
8481            mHistoryCur.batteryLevel = (byte)level;
8482            mHistoryCur.batteryStatus = (byte)status;
8483            mHistoryCur.batteryHealth = (byte)health;
8484            mHistoryCur.batteryPlugType = (byte)plugType;
8485            mHistoryCur.batteryTemperature = (short)temp;
8486            mHistoryCur.batteryVoltage = (char)volt;
8487            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
8488        } else {
8489            boolean changed = false;
8490            if (mHistoryCur.batteryLevel != level) {
8491                mHistoryCur.batteryLevel = (byte)level;
8492                changed = true;
8493
8494                // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
8495                // which will pull external stats.
8496                scheduleSyncExternalStatsLocked("battery-level");
8497            }
8498            if (mHistoryCur.batteryStatus != status) {
8499                mHistoryCur.batteryStatus = (byte)status;
8500                changed = true;
8501            }
8502            if (mHistoryCur.batteryHealth != health) {
8503                mHistoryCur.batteryHealth = (byte)health;
8504                changed = true;
8505            }
8506            if (mHistoryCur.batteryPlugType != plugType) {
8507                mHistoryCur.batteryPlugType = (byte)plugType;
8508                changed = true;
8509            }
8510            if (temp >= (mHistoryCur.batteryTemperature+10)
8511                    || temp <= (mHistoryCur.batteryTemperature-10)) {
8512                mHistoryCur.batteryTemperature = (short)temp;
8513                changed = true;
8514            }
8515            if (volt > (mHistoryCur.batteryVoltage+20)
8516                    || volt < (mHistoryCur.batteryVoltage-20)) {
8517                mHistoryCur.batteryVoltage = (char)volt;
8518                changed = true;
8519            }
8520            long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
8521                    | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
8522                    | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
8523            if (onBattery) {
8524                changed |= setChargingLocked(false);
8525                if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
8526                    mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
8527                            modeBits, elapsedRealtime);
8528                    mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
8529                            modeBits, elapsedRealtime);
8530                    mLastDischargeStepLevel = level;
8531                    mMinDischargeStepLevel = level;
8532                    mInitStepMode = mCurStepMode;
8533                    mModStepMode = 0;
8534                }
8535            } else {
8536                if (level >= 90) {
8537                    // If the battery level is at least 90%, always consider the device to be
8538                    // charging even if it happens to go down a level.
8539                    changed |= setChargingLocked(true);
8540                    mLastChargeStepLevel = level;
8541                } if (!mCharging) {
8542                    if (mLastChargeStepLevel < level) {
8543                        // We have not reporting that we are charging, but the level has now
8544                        // gone up, so consider the state to be charging.
8545                        changed |= setChargingLocked(true);
8546                        mLastChargeStepLevel = level;
8547                    }
8548                } else {
8549                    if (mLastChargeStepLevel > level) {
8550                        // We had reported that the device was charging, but here we are with
8551                        // power connected and the level going down.  Looks like the current
8552                        // power supplied isn't enough, so consider the device to now be
8553                        // discharging.
8554                        changed |= setChargingLocked(false);
8555                        mLastChargeStepLevel = level;
8556                    }
8557                }
8558                if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
8559                    mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
8560                            modeBits, elapsedRealtime);
8561                    mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
8562                            modeBits, elapsedRealtime);
8563                    mLastChargeStepLevel = level;
8564                    mMaxChargeStepLevel = level;
8565                    mInitStepMode = mCurStepMode;
8566                    mModStepMode = 0;
8567                }
8568            }
8569            if (changed) {
8570                addHistoryRecordLocked(elapsedRealtime, uptime);
8571            }
8572        }
8573        if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
8574            // We don't record history while we are plugged in and fully charged.
8575            // The next time we are unplugged, history will be cleared.
8576            mRecordingHistory = DEBUG;
8577        }
8578    }
8579
8580    public long getAwakeTimeBattery() {
8581        return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
8582    }
8583
8584    public long getAwakeTimePlugged() {
8585        return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
8586    }
8587
8588    @Override
8589    public long computeUptime(long curTime, int which) {
8590        switch (which) {
8591            case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
8592            case STATS_CURRENT: return (curTime-mUptimeStart);
8593            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getUptimeStart());
8594        }
8595        return 0;
8596    }
8597
8598    @Override
8599    public long computeRealtime(long curTime, int which) {
8600        switch (which) {
8601            case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
8602            case STATS_CURRENT: return (curTime-mRealtimeStart);
8603            case STATS_SINCE_UNPLUGGED: return (curTime-mOnBatteryTimeBase.getRealtimeStart());
8604        }
8605        return 0;
8606    }
8607
8608    @Override
8609    public long computeBatteryUptime(long curTime, int which) {
8610        return mOnBatteryTimeBase.computeUptime(curTime, which);
8611    }
8612
8613    @Override
8614    public long computeBatteryRealtime(long curTime, int which) {
8615        return mOnBatteryTimeBase.computeRealtime(curTime, which);
8616    }
8617
8618    @Override
8619    public long computeBatteryScreenOffUptime(long curTime, int which) {
8620        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
8621    }
8622
8623    @Override
8624    public long computeBatteryScreenOffRealtime(long curTime, int which) {
8625        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
8626    }
8627
8628    private long computeTimePerLevel(long[] steps, int numSteps) {
8629        // For now we'll do a simple average across all steps.
8630        if (numSteps <= 0) {
8631            return -1;
8632        }
8633        long total = 0;
8634        for (int i=0; i<numSteps; i++) {
8635            total += steps[i] & STEP_LEVEL_TIME_MASK;
8636        }
8637        return total / numSteps;
8638        /*
8639        long[] buckets = new long[numSteps];
8640        int numBuckets = 0;
8641        int numToAverage = 4;
8642        int i = 0;
8643        while (i < numSteps) {
8644            long totalTime = 0;
8645            int num = 0;
8646            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
8647                totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
8648                num++;
8649            }
8650            buckets[numBuckets] = totalTime / num;
8651            numBuckets++;
8652            numToAverage *= 2;
8653            i += num;
8654        }
8655        if (numBuckets < 1) {
8656            return -1;
8657        }
8658        long averageTime = buckets[numBuckets-1];
8659        for (i=numBuckets-2; i>=0; i--) {
8660            averageTime = (averageTime + buckets[i]) / 2;
8661        }
8662        return averageTime;
8663        */
8664    }
8665
8666    @Override
8667    public long computeBatteryTimeRemaining(long curTime) {
8668        if (!mOnBattery) {
8669            return -1;
8670        }
8671        /* Simple implementation just looks at the average discharge per level across the
8672           entire sample period.
8673        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
8674        if (discharge < 2) {
8675            return -1;
8676        }
8677        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
8678        if (duration < 1000*1000) {
8679            return -1;
8680        }
8681        long usPerLevel = duration/discharge;
8682        return usPerLevel * mCurrentBatteryLevel;
8683        */
8684        if (mDischargeStepTracker.mNumStepDurations < 1) {
8685            return -1;
8686        }
8687        long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
8688        if (msPerLevel <= 0) {
8689            return -1;
8690        }
8691        return (msPerLevel * mCurrentBatteryLevel) * 1000;
8692    }
8693
8694    @Override
8695    public LevelStepTracker getDischargeLevelStepTracker() {
8696        return mDischargeStepTracker;
8697    }
8698
8699    @Override
8700    public LevelStepTracker getDailyDischargeLevelStepTracker() {
8701        return mDailyDischargeStepTracker;
8702    }
8703
8704    @Override
8705    public long computeChargeTimeRemaining(long curTime) {
8706        if (mOnBattery) {
8707            // Not yet working.
8708            return -1;
8709        }
8710        /* Broken
8711        int curLevel = mCurrentBatteryLevel;
8712        int plugLevel = mDischargePlugLevel;
8713        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
8714            return -1;
8715        }
8716        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
8717        if (duration < 1000*1000) {
8718            return -1;
8719        }
8720        long usPerLevel = duration/(curLevel-plugLevel);
8721        return usPerLevel * (100-curLevel);
8722        */
8723        if (mChargeStepTracker.mNumStepDurations < 1) {
8724            return -1;
8725        }
8726        long msPerLevel = mChargeStepTracker.computeTimePerLevel();
8727        if (msPerLevel <= 0) {
8728            return -1;
8729        }
8730        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
8731    }
8732
8733    @Override
8734    public LevelStepTracker getChargeLevelStepTracker() {
8735        return mChargeStepTracker;
8736    }
8737
8738    @Override
8739    public LevelStepTracker getDailyChargeLevelStepTracker() {
8740        return mDailyChargeStepTracker;
8741    }
8742
8743    @Override
8744    public ArrayList<PackageChange> getDailyPackageChanges() {
8745        return mDailyPackageChanges;
8746    }
8747
8748    long getBatteryUptimeLocked() {
8749        return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
8750    }
8751
8752    @Override
8753    public long getBatteryUptime(long curTime) {
8754        return mOnBatteryTimeBase.getUptime(curTime);
8755    }
8756
8757    @Override
8758    public long getBatteryRealtime(long curTime) {
8759        return mOnBatteryTimeBase.getRealtime(curTime);
8760    }
8761
8762    @Override
8763    public int getDischargeStartLevel() {
8764        synchronized(this) {
8765            return getDischargeStartLevelLocked();
8766        }
8767    }
8768
8769    public int getDischargeStartLevelLocked() {
8770            return mDischargeUnplugLevel;
8771    }
8772
8773    @Override
8774    public int getDischargeCurrentLevel() {
8775        synchronized(this) {
8776            return getDischargeCurrentLevelLocked();
8777        }
8778    }
8779
8780    public int getDischargeCurrentLevelLocked() {
8781        return mDischargeCurrentLevel;
8782    }
8783
8784    @Override
8785    public int getLowDischargeAmountSinceCharge() {
8786        synchronized(this) {
8787            int val = mLowDischargeAmountSinceCharge;
8788            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
8789                val += mDischargeUnplugLevel-mDischargeCurrentLevel-1;
8790            }
8791            return val;
8792        }
8793    }
8794
8795    @Override
8796    public int getHighDischargeAmountSinceCharge() {
8797        synchronized(this) {
8798            int val = mHighDischargeAmountSinceCharge;
8799            if (mOnBattery && mDischargeCurrentLevel < mDischargeUnplugLevel) {
8800                val += mDischargeUnplugLevel-mDischargeCurrentLevel;
8801            }
8802            return val;
8803        }
8804    }
8805
8806    @Override
8807    public int getDischargeAmount(int which) {
8808        int dischargeAmount = which == STATS_SINCE_CHARGED
8809                ? getHighDischargeAmountSinceCharge()
8810                : (getDischargeStartLevel() - getDischargeCurrentLevel());
8811        if (dischargeAmount < 0) {
8812            dischargeAmount = 0;
8813        }
8814        return dischargeAmount;
8815    }
8816
8817    public int getDischargeAmountScreenOn() {
8818        synchronized(this) {
8819            int val = mDischargeAmountScreenOn;
8820            if (mOnBattery && mScreenState == Display.STATE_ON
8821                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
8822                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
8823            }
8824            return val;
8825        }
8826    }
8827
8828    public int getDischargeAmountScreenOnSinceCharge() {
8829        synchronized(this) {
8830            int val = mDischargeAmountScreenOnSinceCharge;
8831            if (mOnBattery && mScreenState == Display.STATE_ON
8832                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
8833                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
8834            }
8835            return val;
8836        }
8837    }
8838
8839    public int getDischargeAmountScreenOff() {
8840        synchronized(this) {
8841            int val = mDischargeAmountScreenOff;
8842            if (mOnBattery && mScreenState != Display.STATE_ON
8843                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
8844                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
8845            }
8846            return val;
8847        }
8848    }
8849
8850    public int getDischargeAmountScreenOffSinceCharge() {
8851        synchronized(this) {
8852            int val = mDischargeAmountScreenOffSinceCharge;
8853            if (mOnBattery && mScreenState != Display.STATE_ON
8854                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
8855                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
8856            }
8857            return val;
8858        }
8859    }
8860
8861    /**
8862     * Retrieve the statistics object for a particular uid, creating if needed.
8863     */
8864    public Uid getUidStatsLocked(int uid) {
8865        Uid u = mUidStats.get(uid);
8866        if (u == null) {
8867            u = new Uid(uid);
8868            mUidStats.put(uid, u);
8869        }
8870        return u;
8871    }
8872
8873    /**
8874     * Remove the statistics object for a particular uid.
8875     */
8876    public void removeUidStatsLocked(int uid) {
8877        mKernelUidCpuTimeReader.removeUid(uid);
8878        mUidStats.remove(uid);
8879    }
8880
8881    /**
8882     * Retrieve the statistics object for a particular process, creating
8883     * if needed.
8884     */
8885    public Uid.Proc getProcessStatsLocked(int uid, String name) {
8886        uid = mapUid(uid);
8887        Uid u = getUidStatsLocked(uid);
8888        return u.getProcessStatsLocked(name);
8889    }
8890
8891    /**
8892     * Retrieve the statistics object for a particular process, creating
8893     * if needed.
8894     */
8895    public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
8896        uid = mapUid(uid);
8897        Uid u = getUidStatsLocked(uid);
8898        return u.getPackageStatsLocked(pkg);
8899    }
8900
8901    /**
8902     * Retrieve the statistics object for a particular service, creating
8903     * if needed.
8904     */
8905    public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
8906        uid = mapUid(uid);
8907        Uid u = getUidStatsLocked(uid);
8908        return u.getServiceStatsLocked(pkg, name);
8909    }
8910
8911    public void shutdownLocked() {
8912        recordShutdownLocked(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
8913        writeSyncLocked();
8914        mShuttingDown = true;
8915    }
8916
8917    Parcel mPendingWrite = null;
8918    final ReentrantLock mWriteLock = new ReentrantLock();
8919
8920    public void writeAsyncLocked() {
8921        writeLocked(false);
8922    }
8923
8924    public void writeSyncLocked() {
8925        writeLocked(true);
8926    }
8927
8928    void writeLocked(boolean sync) {
8929        if (mFile == null) {
8930            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
8931            return;
8932        }
8933
8934        if (mShuttingDown) {
8935            return;
8936        }
8937
8938        Parcel out = Parcel.obtain();
8939        writeSummaryToParcel(out, true);
8940        mLastWriteTime = SystemClock.elapsedRealtime();
8941
8942        if (mPendingWrite != null) {
8943            mPendingWrite.recycle();
8944        }
8945        mPendingWrite = out;
8946
8947        if (sync) {
8948            commitPendingDataToDisk();
8949        } else {
8950            BackgroundThread.getHandler().post(new Runnable() {
8951                @Override public void run() {
8952                    commitPendingDataToDisk();
8953                }
8954            });
8955        }
8956    }
8957
8958    public void commitPendingDataToDisk() {
8959        final Parcel next;
8960        synchronized (this) {
8961            next = mPendingWrite;
8962            mPendingWrite = null;
8963            if (next == null) {
8964                return;
8965            }
8966
8967            mWriteLock.lock();
8968        }
8969
8970        try {
8971            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
8972            stream.write(next.marshall());
8973            stream.flush();
8974            FileUtils.sync(stream);
8975            stream.close();
8976            mFile.commit();
8977        } catch (IOException e) {
8978            Slog.w("BatteryStats", "Error writing battery statistics", e);
8979            mFile.rollback();
8980        } finally {
8981            next.recycle();
8982            mWriteLock.unlock();
8983        }
8984    }
8985
8986    public void readLocked() {
8987        if (mDailyFile != null) {
8988            readDailyStatsLocked();
8989        }
8990
8991        if (mFile == null) {
8992            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
8993            return;
8994        }
8995
8996        mUidStats.clear();
8997
8998        try {
8999            File file = mFile.chooseForRead();
9000            if (!file.exists()) {
9001                return;
9002            }
9003            FileInputStream stream = new FileInputStream(file);
9004
9005            byte[] raw = BatteryStatsHelper.readFully(stream);
9006            Parcel in = Parcel.obtain();
9007            in.unmarshall(raw, 0, raw.length);
9008            in.setDataPosition(0);
9009            stream.close();
9010
9011            readSummaryFromParcel(in);
9012        } catch(Exception e) {
9013            Slog.e("BatteryStats", "Error reading battery statistics", e);
9014            resetAllStatsLocked();
9015        }
9016
9017        mEndPlatformVersion = Build.ID;
9018
9019        if (mHistoryBuffer.dataPosition() > 0) {
9020            mRecordingHistory = true;
9021            final long elapsedRealtime = SystemClock.elapsedRealtime();
9022            final long uptime = SystemClock.uptimeMillis();
9023            if (USE_OLD_HISTORY) {
9024                addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
9025            }
9026            addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
9027            startRecordingHistory(elapsedRealtime, uptime, false);
9028        }
9029
9030        recordDailyStatsIfNeededLocked(false);
9031    }
9032
9033    public int describeContents() {
9034        return 0;
9035    }
9036
9037    void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
9038        final long historyBaseTime = in.readLong();
9039
9040        mHistoryBuffer.setDataSize(0);
9041        mHistoryBuffer.setDataPosition(0);
9042        mHistoryTagPool.clear();
9043        mNextHistoryTagIdx = 0;
9044        mNumHistoryTagChars = 0;
9045
9046        int numTags = in.readInt();
9047        for (int i=0; i<numTags; i++) {
9048            int idx = in.readInt();
9049            String str = in.readString();
9050            if (str == null) {
9051                throw new ParcelFormatException("null history tag string");
9052            }
9053            int uid = in.readInt();
9054            HistoryTag tag = new HistoryTag();
9055            tag.string = str;
9056            tag.uid = uid;
9057            tag.poolIdx = idx;
9058            mHistoryTagPool.put(tag, idx);
9059            if (idx >= mNextHistoryTagIdx) {
9060                mNextHistoryTagIdx = idx+1;
9061            }
9062            mNumHistoryTagChars += tag.string.length() + 1;
9063        }
9064
9065        int bufSize = in.readInt();
9066        int curPos = in.dataPosition();
9067        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
9068            throw new ParcelFormatException("File corrupt: history data buffer too large " +
9069                    bufSize);
9070        } else if ((bufSize&~3) != bufSize) {
9071            throw new ParcelFormatException("File corrupt: history data buffer not aligned " +
9072                    bufSize);
9073        } else {
9074            if (DEBUG_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
9075                    + " bytes at " + curPos);
9076            mHistoryBuffer.appendFrom(in, curPos, bufSize);
9077            in.setDataPosition(curPos + bufSize);
9078        }
9079
9080        if (andOldHistory) {
9081            readOldHistory(in);
9082        }
9083
9084        if (DEBUG_HISTORY) {
9085            StringBuilder sb = new StringBuilder(128);
9086            sb.append("****************** OLD mHistoryBaseTime: ");
9087            TimeUtils.formatDuration(mHistoryBaseTime, sb);
9088            Slog.i(TAG, sb.toString());
9089        }
9090        mHistoryBaseTime = historyBaseTime;
9091        if (DEBUG_HISTORY) {
9092            StringBuilder sb = new StringBuilder(128);
9093            sb.append("****************** NEW mHistoryBaseTime: ");
9094            TimeUtils.formatDuration(mHistoryBaseTime, sb);
9095            Slog.i(TAG, sb.toString());
9096        }
9097
9098        // We are just arbitrarily going to insert 1 minute from the sample of
9099        // the last run until samples in this run.
9100        if (mHistoryBaseTime > 0) {
9101            long oldnow = SystemClock.elapsedRealtime();
9102            mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
9103            if (DEBUG_HISTORY) {
9104                StringBuilder sb = new StringBuilder(128);
9105                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
9106                TimeUtils.formatDuration(mHistoryBaseTime, sb);
9107                Slog.i(TAG, sb.toString());
9108            }
9109        }
9110    }
9111
9112    void readOldHistory(Parcel in) {
9113        if (!USE_OLD_HISTORY) {
9114            return;
9115        }
9116        mHistory = mHistoryEnd = mHistoryCache = null;
9117        long time;
9118        while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
9119            HistoryItem rec = new HistoryItem(time, in);
9120            addHistoryRecordLocked(rec);
9121        }
9122    }
9123
9124    void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
9125        if (DEBUG_HISTORY) {
9126            StringBuilder sb = new StringBuilder(128);
9127            sb.append("****************** WRITING mHistoryBaseTime: ");
9128            TimeUtils.formatDuration(mHistoryBaseTime, sb);
9129            sb.append(" mLastHistoryElapsedRealtime: ");
9130            TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
9131            Slog.i(TAG, sb.toString());
9132        }
9133        out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
9134        if (!inclData) {
9135            out.writeInt(0);
9136            out.writeInt(0);
9137            return;
9138        }
9139        out.writeInt(mHistoryTagPool.size());
9140        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
9141            HistoryTag tag = ent.getKey();
9142            out.writeInt(ent.getValue());
9143            out.writeString(tag.string);
9144            out.writeInt(tag.uid);
9145        }
9146        out.writeInt(mHistoryBuffer.dataSize());
9147        if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
9148                + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
9149        out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
9150
9151        if (andOldHistory) {
9152            writeOldHistory(out);
9153        }
9154    }
9155
9156    void writeOldHistory(Parcel out) {
9157        if (!USE_OLD_HISTORY) {
9158            return;
9159        }
9160        HistoryItem rec = mHistory;
9161        while (rec != null) {
9162            if (rec.time >= 0) rec.writeToParcel(out, 0);
9163            rec = rec.next;
9164        }
9165        out.writeLong(-1);
9166    }
9167
9168    public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
9169        final int version = in.readInt();
9170        if (version != VERSION) {
9171            Slog.w("BatteryStats", "readFromParcel: version got " + version
9172                + ", expected " + VERSION + "; erasing old stats");
9173            return;
9174        }
9175
9176        readHistory(in, true);
9177
9178        mStartCount = in.readInt();
9179        mUptime = in.readLong();
9180        mRealtime = in.readLong();
9181        mStartClockTime = in.readLong();
9182        mStartPlatformVersion = in.readString();
9183        mEndPlatformVersion = in.readString();
9184        mOnBatteryTimeBase.readSummaryFromParcel(in);
9185        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
9186        mDischargeUnplugLevel = in.readInt();
9187        mDischargePlugLevel = in.readInt();
9188        mDischargeCurrentLevel = in.readInt();
9189        mCurrentBatteryLevel = in.readInt();
9190        mLowDischargeAmountSinceCharge = in.readInt();
9191        mHighDischargeAmountSinceCharge = in.readInt();
9192        mDischargeAmountScreenOnSinceCharge = in.readInt();
9193        mDischargeAmountScreenOffSinceCharge = in.readInt();
9194        mDischargeStepTracker.readFromParcel(in);
9195        mChargeStepTracker.readFromParcel(in);
9196        mDailyDischargeStepTracker.readFromParcel(in);
9197        mDailyChargeStepTracker.readFromParcel(in);
9198        int NPKG = in.readInt();
9199        if (NPKG > 0) {
9200            mDailyPackageChanges = new ArrayList<>(NPKG);
9201            while (NPKG > 0) {
9202                NPKG--;
9203                PackageChange pc = new PackageChange();
9204                pc.mPackageName = in.readString();
9205                pc.mUpdate = in.readInt() != 0;
9206                pc.mVersionCode = in.readInt();
9207                mDailyPackageChanges.add(pc);
9208            }
9209        } else {
9210            mDailyPackageChanges = null;
9211        }
9212        mDailyStartTime = in.readLong();
9213        mNextMinDailyDeadline = in.readLong();
9214        mNextMaxDailyDeadline = in.readLong();
9215
9216        mStartCount++;
9217
9218        mScreenState = Display.STATE_UNKNOWN;
9219        mScreenOnTimer.readSummaryFromParcelLocked(in);
9220        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9221            mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
9222        }
9223        mInteractive = false;
9224        mInteractiveTimer.readSummaryFromParcelLocked(in);
9225        mPhoneOn = false;
9226        mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
9227        mDeviceIdleModeEnabledTimer.readSummaryFromParcelLocked(in);
9228        mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
9229        mPhoneOnTimer.readSummaryFromParcelLocked(in);
9230        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9231            mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
9232        }
9233        mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
9234        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9235            mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
9236        }
9237        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9238            mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
9239            mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
9240        }
9241        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9242        mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
9243        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
9244        mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
9245        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
9246        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
9247        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9248        mWifiOn = false;
9249        mWifiOnTimer.readSummaryFromParcelLocked(in);
9250        mGlobalWifiRunning = false;
9251        mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
9252        for (int i=0; i<NUM_WIFI_STATES; i++) {
9253            mWifiStateTimer[i].readSummaryFromParcelLocked(in);
9254        }
9255        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9256            mWifiSupplStateTimer[i].readSummaryFromParcelLocked(in);
9257        }
9258        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9259            mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
9260        }
9261        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9262            mBluetoothActivityCounters[i].readSummaryFromParcelLocked(in);
9263        }
9264        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9265            mWifiActivityCounters[i].readSummaryFromParcelLocked(in);
9266        }
9267
9268        mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
9269        mFlashlightOnNesting = 0;
9270        mFlashlightOnTimer.readSummaryFromParcelLocked(in);
9271        mCameraOnNesting = 0;
9272        mCameraOnTimer.readSummaryFromParcelLocked(in);
9273
9274        int NKW = in.readInt();
9275        if (NKW > 10000) {
9276            throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
9277        }
9278        for (int ikw = 0; ikw < NKW; ikw++) {
9279            if (in.readInt() != 0) {
9280                String kwltName = in.readString();
9281                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
9282            }
9283        }
9284
9285        int NWR = in.readInt();
9286        if (NWR > 10000) {
9287            throw new ParcelFormatException("File corrupt: too many wakeup reasons " + NWR);
9288        }
9289        for (int iwr = 0; iwr < NWR; iwr++) {
9290            if (in.readInt() != 0) {
9291                String reasonName = in.readString();
9292                getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
9293            }
9294        }
9295
9296        final int NU = in.readInt();
9297        if (NU > 10000) {
9298            throw new ParcelFormatException("File corrupt: too many uids " + NU);
9299        }
9300        for (int iu = 0; iu < NU; iu++) {
9301            int uid = in.readInt();
9302            Uid u = new Uid(uid);
9303            mUidStats.put(uid, u);
9304
9305            u.mWifiRunning = false;
9306            if (in.readInt() != 0) {
9307                u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
9308            }
9309            u.mFullWifiLockOut = false;
9310            if (in.readInt() != 0) {
9311                u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
9312            }
9313            u.mWifiScanStarted = false;
9314            if (in.readInt() != 0) {
9315                u.mWifiScanTimer.readSummaryFromParcelLocked(in);
9316            }
9317            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
9318            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9319                if (in.readInt() != 0) {
9320                    u.makeWifiBatchedScanBin(i, null);
9321                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
9322                }
9323            }
9324            u.mWifiMulticastEnabled = false;
9325            if (in.readInt() != 0) {
9326                u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
9327            }
9328            if (in.readInt() != 0) {
9329                u.createAudioTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9330            }
9331            if (in.readInt() != 0) {
9332                u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9333            }
9334            if (in.readInt() != 0) {
9335                u.createFlashlightTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9336            }
9337            if (in.readInt() != 0) {
9338                u.createCameraTurnedOnTimerLocked().readSummaryFromParcelLocked(in);
9339            }
9340            if (in.readInt() != 0) {
9341                u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
9342            }
9343            u.mProcessState = Uid.PROCESS_STATE_NONE;
9344            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
9345                if (in.readInt() != 0) {
9346                    u.makeProcessState(i, null);
9347                    u.mProcessStateTimer[i].readSummaryFromParcelLocked(in);
9348                }
9349            }
9350            if (in.readInt() != 0) {
9351                u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in);
9352            }
9353
9354            if (in.readInt() != 0) {
9355                if (u.mUserActivityCounters == null) {
9356                    u.initUserActivityLocked();
9357                }
9358                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
9359                    u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
9360                }
9361            }
9362
9363            if (in.readInt() != 0) {
9364                if (u.mNetworkByteActivityCounters == null) {
9365                    u.initNetworkActivityLocked();
9366                }
9367                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9368                    u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
9369                    u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
9370                }
9371                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
9372                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
9373            }
9374
9375            u.mUserCpuTime.readSummaryFromParcelLocked(in);
9376            u.mSystemCpuTime.readSummaryFromParcelLocked(in);
9377            u.mCpuPower.readSummaryFromParcelLocked(in);
9378
9379            if (in.readInt() != 0) {
9380                final int numClusters = in.readInt();
9381                if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
9382                    throw new ParcelFormatException("Incompatible cpu cluster arrangement");
9383                }
9384
9385                u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
9386                for (int cluster = 0; cluster < numClusters; cluster++) {
9387                    if (in.readInt() != 0) {
9388                        final int NSB = in.readInt();
9389                        if (mPowerProfile != null &&
9390                                mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
9391                            throw new ParcelFormatException("File corrupt: too many speed bins " +
9392                                    NSB);
9393                        }
9394
9395                        u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB];
9396                        for (int speed = 0; speed < NSB; speed++) {
9397                            if (in.readInt() != 0) {
9398                                u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter(
9399                                        mOnBatteryTimeBase);
9400                                u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in);
9401                            }
9402                        }
9403                    } else {
9404                        u.mCpuClusterSpeed[cluster] = null;
9405                    }
9406                }
9407            } else {
9408                u.mCpuClusterSpeed = null;
9409            }
9410
9411            int NW = in.readInt();
9412            if (NW > 100) {
9413                throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
9414            }
9415            for (int iw = 0; iw < NW; iw++) {
9416                String wlName = in.readString();
9417                u.readWakeSummaryFromParcelLocked(wlName, in);
9418            }
9419
9420            int NS = in.readInt();
9421            if (NS > 100) {
9422                throw new ParcelFormatException("File corrupt: too many syncs " + NS);
9423            }
9424            for (int is = 0; is < NS; is++) {
9425                String name = in.readString();
9426                u.readSyncSummaryFromParcelLocked(name, in);
9427            }
9428
9429            int NJ = in.readInt();
9430            if (NJ > 100) {
9431                throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
9432            }
9433            for (int ij = 0; ij < NJ; ij++) {
9434                String name = in.readString();
9435                u.readJobSummaryFromParcelLocked(name, in);
9436            }
9437
9438            int NP = in.readInt();
9439            if (NP > 1000) {
9440                throw new ParcelFormatException("File corrupt: too many sensors " + NP);
9441            }
9442            for (int is = 0; is < NP; is++) {
9443                int seNumber = in.readInt();
9444                if (in.readInt() != 0) {
9445                    u.getSensorTimerLocked(seNumber, true)
9446                            .readSummaryFromParcelLocked(in);
9447                }
9448            }
9449
9450            NP = in.readInt();
9451            if (NP > 1000) {
9452                throw new ParcelFormatException("File corrupt: too many processes " + NP);
9453            }
9454            for (int ip = 0; ip < NP; ip++) {
9455                String procName = in.readString();
9456                Uid.Proc p = u.getProcessStatsLocked(procName);
9457                p.mUserTime = p.mLoadedUserTime = in.readLong();
9458                p.mSystemTime = p.mLoadedSystemTime = in.readLong();
9459                p.mForegroundTime = p.mLoadedForegroundTime = in.readLong();
9460                p.mStarts = p.mLoadedStarts = in.readInt();
9461                p.mNumCrashes = p.mLoadedNumCrashes = in.readInt();
9462                p.mNumAnrs = p.mLoadedNumAnrs = in.readInt();
9463                p.readExcessivePowerFromParcelLocked(in);
9464            }
9465
9466            NP = in.readInt();
9467            if (NP > 10000) {
9468                throw new ParcelFormatException("File corrupt: too many packages " + NP);
9469            }
9470            for (int ip = 0; ip < NP; ip++) {
9471                String pkgName = in.readString();
9472                Uid.Pkg p = u.getPackageStatsLocked(pkgName);
9473                final int NWA = in.readInt();
9474                if (NWA > 1000) {
9475                    throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
9476                }
9477                p.mWakeupAlarms.clear();
9478                for (int iwa=0; iwa<NWA; iwa++) {
9479                    String tag = in.readString();
9480                    Counter c = new Counter(mOnBatteryTimeBase);
9481                    c.readSummaryFromParcelLocked(in);
9482                    p.mWakeupAlarms.put(tag, c);
9483                }
9484                NS = in.readInt();
9485                if (NS > 1000) {
9486                    throw new ParcelFormatException("File corrupt: too many services " + NS);
9487                }
9488                for (int is = 0; is < NS; is++) {
9489                    String servName = in.readString();
9490                    Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
9491                    s.mStartTime = s.mLoadedStartTime = in.readLong();
9492                    s.mStarts = s.mLoadedStarts = in.readInt();
9493                    s.mLaunches = s.mLoadedLaunches = in.readInt();
9494                }
9495            }
9496        }
9497    }
9498
9499    /**
9500     * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
9501     * disk.  This format does not allow a lossless round-trip.
9502     *
9503     * @param out the Parcel to be written to.
9504     */
9505    public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
9506        pullPendingStateUpdatesLocked();
9507
9508        // Pull the clock time.  This may update the time and make a new history entry
9509        // if we had originally pulled a time before the RTC was set.
9510        long startClockTime = getStartClockTime();
9511
9512        final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
9513        final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
9514
9515        out.writeInt(VERSION);
9516
9517        writeHistory(out, inclHistory, true);
9518
9519        out.writeInt(mStartCount);
9520        out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
9521        out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
9522        out.writeLong(startClockTime);
9523        out.writeString(mStartPlatformVersion);
9524        out.writeString(mEndPlatformVersion);
9525        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
9526        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
9527        out.writeInt(mDischargeUnplugLevel);
9528        out.writeInt(mDischargePlugLevel);
9529        out.writeInt(mDischargeCurrentLevel);
9530        out.writeInt(mCurrentBatteryLevel);
9531        out.writeInt(getLowDischargeAmountSinceCharge());
9532        out.writeInt(getHighDischargeAmountSinceCharge());
9533        out.writeInt(getDischargeAmountScreenOnSinceCharge());
9534        out.writeInt(getDischargeAmountScreenOffSinceCharge());
9535        mDischargeStepTracker.writeToParcel(out);
9536        mChargeStepTracker.writeToParcel(out);
9537        mDailyDischargeStepTracker.writeToParcel(out);
9538        mDailyChargeStepTracker.writeToParcel(out);
9539        if (mDailyPackageChanges != null) {
9540            final int NPKG = mDailyPackageChanges.size();
9541            out.writeInt(NPKG);
9542            for (int i=0; i<NPKG; i++) {
9543                PackageChange pc = mDailyPackageChanges.get(i);
9544                out.writeString(pc.mPackageName);
9545                out.writeInt(pc.mUpdate ? 1 : 0);
9546                out.writeInt(pc.mVersionCode);
9547            }
9548        } else {
9549            out.writeInt(0);
9550        }
9551        out.writeLong(mDailyStartTime);
9552        out.writeLong(mNextMinDailyDeadline);
9553        out.writeLong(mNextMaxDailyDeadline);
9554
9555        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9556        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9557            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9558        }
9559        mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9560        mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9561        mDeviceIdleModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9562        mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9563        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9564        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9565            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9566        }
9567        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9568        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9569            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9570        }
9571        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9572            mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
9573            mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
9574        }
9575        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9576        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9577        mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
9578        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
9579        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
9580        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9581        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9582        for (int i=0; i<NUM_WIFI_STATES; i++) {
9583            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9584        }
9585        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9586            mWifiSupplStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9587        }
9588        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9589            mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9590        }
9591        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9592            mBluetoothActivityCounters[i].writeSummaryFromParcelLocked(out);
9593        }
9594        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9595            mWifiActivityCounters[i].writeSummaryFromParcelLocked(out);
9596        }
9597        out.writeInt(mNumConnectivityChange);
9598        mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9599        mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9600
9601        out.writeInt(mKernelWakelockStats.size());
9602        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
9603            Timer kwlt = ent.getValue();
9604            if (kwlt != null) {
9605                out.writeInt(1);
9606                out.writeString(ent.getKey());
9607                kwlt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9608            } else {
9609                out.writeInt(0);
9610            }
9611        }
9612
9613        out.writeInt(mWakeupReasonStats.size());
9614        for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
9615            SamplingTimer timer = ent.getValue();
9616            if (timer != null) {
9617                out.writeInt(1);
9618                out.writeString(ent.getKey());
9619                timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9620            } else {
9621                out.writeInt(0);
9622            }
9623        }
9624
9625        final int NU = mUidStats.size();
9626        out.writeInt(NU);
9627        for (int iu = 0; iu < NU; iu++) {
9628            out.writeInt(mUidStats.keyAt(iu));
9629            Uid u = mUidStats.valueAt(iu);
9630
9631            if (u.mWifiRunningTimer != null) {
9632                out.writeInt(1);
9633                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9634            } else {
9635                out.writeInt(0);
9636            }
9637            if (u.mFullWifiLockTimer != null) {
9638                out.writeInt(1);
9639                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9640            } else {
9641                out.writeInt(0);
9642            }
9643            if (u.mWifiScanTimer != null) {
9644                out.writeInt(1);
9645                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9646            } else {
9647                out.writeInt(0);
9648            }
9649            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
9650                if (u.mWifiBatchedScanTimer[i] != null) {
9651                    out.writeInt(1);
9652                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9653                } else {
9654                    out.writeInt(0);
9655                }
9656            }
9657            if (u.mWifiMulticastTimer != null) {
9658                out.writeInt(1);
9659                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9660            } else {
9661                out.writeInt(0);
9662            }
9663            if (u.mAudioTurnedOnTimer != null) {
9664                out.writeInt(1);
9665                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9666            } else {
9667                out.writeInt(0);
9668            }
9669            if (u.mVideoTurnedOnTimer != null) {
9670                out.writeInt(1);
9671                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9672            } else {
9673                out.writeInt(0);
9674            }
9675            if (u.mFlashlightTurnedOnTimer != null) {
9676                out.writeInt(1);
9677                u.mFlashlightTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9678            } else {
9679                out.writeInt(0);
9680            }
9681            if (u.mCameraTurnedOnTimer != null) {
9682                out.writeInt(1);
9683                u.mCameraTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9684            } else {
9685                out.writeInt(0);
9686            }
9687            if (u.mForegroundActivityTimer != null) {
9688                out.writeInt(1);
9689                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9690            } else {
9691                out.writeInt(0);
9692            }
9693            for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
9694                if (u.mProcessStateTimer[i] != null) {
9695                    out.writeInt(1);
9696                    u.mProcessStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9697                } else {
9698                    out.writeInt(0);
9699                }
9700            }
9701            if (u.mVibratorOnTimer != null) {
9702                out.writeInt(1);
9703                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9704            } else {
9705                out.writeInt(0);
9706            }
9707
9708            if (u.mUserActivityCounters == null) {
9709                out.writeInt(0);
9710            } else {
9711                out.writeInt(1);
9712                for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
9713                    u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
9714                }
9715            }
9716
9717            if (u.mNetworkByteActivityCounters == null) {
9718                out.writeInt(0);
9719            } else {
9720                out.writeInt(1);
9721                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9722                    u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
9723                    u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
9724                }
9725                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
9726                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
9727            }
9728
9729            u.mUserCpuTime.writeSummaryFromParcelLocked(out);
9730            u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
9731            u.mCpuPower.writeSummaryFromParcelLocked(out);
9732
9733            if (u.mCpuClusterSpeed != null) {
9734                out.writeInt(1);
9735                out.writeInt(u.mCpuClusterSpeed.length);
9736                for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) {
9737                    if (cpuSpeeds != null) {
9738                        out.writeInt(1);
9739                        out.writeInt(cpuSpeeds.length);
9740                        for (LongSamplingCounter c : cpuSpeeds) {
9741                            if (c != null) {
9742                                out.writeInt(1);
9743                                c.writeSummaryFromParcelLocked(out);
9744                            } else {
9745                                out.writeInt(0);
9746                            }
9747                        }
9748                    } else {
9749                        out.writeInt(0);
9750                    }
9751                }
9752            } else {
9753                out.writeInt(0);
9754            }
9755
9756            final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
9757            int NW = wakeStats.size();
9758            out.writeInt(NW);
9759            for (int iw=0; iw<NW; iw++) {
9760                out.writeString(wakeStats.keyAt(iw));
9761                Uid.Wakelock wl = wakeStats.valueAt(iw);
9762                if (wl.mTimerFull != null) {
9763                    out.writeInt(1);
9764                    wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9765                } else {
9766                    out.writeInt(0);
9767                }
9768                if (wl.mTimerPartial != null) {
9769                    out.writeInt(1);
9770                    wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9771                } else {
9772                    out.writeInt(0);
9773                }
9774                if (wl.mTimerWindow != null) {
9775                    out.writeInt(1);
9776                    wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9777                } else {
9778                    out.writeInt(0);
9779                }
9780                if (wl.mTimerDraw != null) {
9781                    out.writeInt(1);
9782                    wl.mTimerDraw.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9783                } else {
9784                    out.writeInt(0);
9785                }
9786            }
9787
9788            final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
9789            int NS = syncStats.size();
9790            out.writeInt(NS);
9791            for (int is=0; is<NS; is++) {
9792                out.writeString(syncStats.keyAt(is));
9793                syncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9794            }
9795
9796            final ArrayMap<String, StopwatchTimer> jobStats = u.mJobStats.getMap();
9797            int NJ = jobStats.size();
9798            out.writeInt(NJ);
9799            for (int ij=0; ij<NJ; ij++) {
9800                out.writeString(jobStats.keyAt(ij));
9801                jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9802            }
9803
9804            int NSE = u.mSensorStats.size();
9805            out.writeInt(NSE);
9806            for (int ise=0; ise<NSE; ise++) {
9807                out.writeInt(u.mSensorStats.keyAt(ise));
9808                Uid.Sensor se = u.mSensorStats.valueAt(ise);
9809                if (se.mTimer != null) {
9810                    out.writeInt(1);
9811                    se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
9812                } else {
9813                    out.writeInt(0);
9814                }
9815            }
9816
9817            int NP = u.mProcessStats.size();
9818            out.writeInt(NP);
9819            for (int ip=0; ip<NP; ip++) {
9820                out.writeString(u.mProcessStats.keyAt(ip));
9821                Uid.Proc ps = u.mProcessStats.valueAt(ip);
9822                out.writeLong(ps.mUserTime);
9823                out.writeLong(ps.mSystemTime);
9824                out.writeLong(ps.mForegroundTime);
9825                out.writeInt(ps.mStarts);
9826                out.writeInt(ps.mNumCrashes);
9827                out.writeInt(ps.mNumAnrs);
9828                ps.writeExcessivePowerToParcelLocked(out);
9829            }
9830
9831            NP = u.mPackageStats.size();
9832            out.writeInt(NP);
9833            if (NP > 0) {
9834                for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
9835                    : u.mPackageStats.entrySet()) {
9836                    out.writeString(ent.getKey());
9837                    Uid.Pkg ps = ent.getValue();
9838                    final int NWA = ps.mWakeupAlarms.size();
9839                    out.writeInt(NWA);
9840                    for (int iwa=0; iwa<NWA; iwa++) {
9841                        out.writeString(ps.mWakeupAlarms.keyAt(iwa));
9842                        ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
9843                    }
9844                    NS = ps.mServiceStats.size();
9845                    out.writeInt(NS);
9846                    for (int is=0; is<NS; is++) {
9847                        out.writeString(ps.mServiceStats.keyAt(is));
9848                        BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
9849                        long time = ss.getStartTimeToNowLocked(
9850                                mOnBatteryTimeBase.getUptime(NOW_SYS));
9851                        out.writeLong(time);
9852                        out.writeInt(ss.mStarts);
9853                        out.writeInt(ss.mLaunches);
9854                    }
9855                }
9856            }
9857        }
9858    }
9859
9860    public void readFromParcel(Parcel in) {
9861        readFromParcelLocked(in);
9862    }
9863
9864    void readFromParcelLocked(Parcel in) {
9865        int magic = in.readInt();
9866        if (magic != MAGIC) {
9867            throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
9868        }
9869
9870        readHistory(in, false);
9871
9872        mStartCount = in.readInt();
9873        mStartClockTime = in.readLong();
9874        mStartPlatformVersion = in.readString();
9875        mEndPlatformVersion = in.readString();
9876        mUptime = in.readLong();
9877        mUptimeStart = in.readLong();
9878        mRealtime = in.readLong();
9879        mRealtimeStart = in.readLong();
9880        mOnBattery = in.readInt() != 0;
9881        mOnBatteryInternal = false; // we are no longer really running.
9882        mOnBatteryTimeBase.readFromParcel(in);
9883        mOnBatteryScreenOffTimeBase.readFromParcel(in);
9884
9885        mScreenState = Display.STATE_UNKNOWN;
9886        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
9887        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
9888            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
9889                    in);
9890        }
9891        mInteractive = false;
9892        mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase, in);
9893        mPhoneOn = false;
9894        mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
9895        mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
9896        mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase, in);
9897        mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
9898        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
9899            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
9900                    null, mOnBatteryTimeBase, in);
9901        }
9902        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase, in);
9903        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
9904            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
9905                    null, mOnBatteryTimeBase, in);
9906        }
9907        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
9908            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9909            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9910        }
9911        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9912        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in);
9913        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase,
9914                in);
9915        mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
9916        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
9917        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
9918        mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
9919        mWifiOn = false;
9920        mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase, in);
9921        mGlobalWifiRunning = false;
9922        mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase, in);
9923        for (int i=0; i<NUM_WIFI_STATES; i++) {
9924            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
9925                    null, mOnBatteryTimeBase, in);
9926        }
9927        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
9928            mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i,
9929                    null, mOnBatteryTimeBase, in);
9930        }
9931        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
9932            mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
9933                    null, mOnBatteryTimeBase, in);
9934        }
9935        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9936            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9937        }
9938        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
9939            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
9940        }
9941
9942        mHasWifiEnergyReporting = in.readInt() != 0;
9943        mHasBluetoothEnergyReporting = in.readInt() != 0;
9944        mNumConnectivityChange = in.readInt();
9945        mLoadedNumConnectivityChange = in.readInt();
9946        mUnpluggedNumConnectivityChange = in.readInt();
9947        mAudioOnNesting = 0;
9948        mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
9949        mVideoOnNesting = 0;
9950        mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
9951        mFlashlightOnNesting = 0;
9952        mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
9953        mCameraOnNesting = 0;
9954        mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase, in);
9955        mDischargeUnplugLevel = in.readInt();
9956        mDischargePlugLevel = in.readInt();
9957        mDischargeCurrentLevel = in.readInt();
9958        mCurrentBatteryLevel = in.readInt();
9959        mLowDischargeAmountSinceCharge = in.readInt();
9960        mHighDischargeAmountSinceCharge = in.readInt();
9961        mDischargeAmountScreenOn = in.readInt();
9962        mDischargeAmountScreenOnSinceCharge = in.readInt();
9963        mDischargeAmountScreenOff = in.readInt();
9964        mDischargeAmountScreenOffSinceCharge = in.readInt();
9965        mDischargeStepTracker.readFromParcel(in);
9966        mChargeStepTracker.readFromParcel(in);
9967        mLastWriteTime = in.readLong();
9968
9969        mKernelWakelockStats.clear();
9970        int NKW = in.readInt();
9971        for (int ikw = 0; ikw < NKW; ikw++) {
9972            if (in.readInt() != 0) {
9973                String wakelockName = in.readString();
9974                SamplingTimer kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, in);
9975                mKernelWakelockStats.put(wakelockName, kwlt);
9976            }
9977        }
9978
9979        mWakeupReasonStats.clear();
9980        int NWR = in.readInt();
9981        for (int iwr = 0; iwr < NWR; iwr++) {
9982            if (in.readInt() != 0) {
9983                String reasonName = in.readString();
9984                SamplingTimer timer = new SamplingTimer(mOnBatteryTimeBase, in);
9985                mWakeupReasonStats.put(reasonName, timer);
9986            }
9987        }
9988
9989        mPartialTimers.clear();
9990        mFullTimers.clear();
9991        mWindowTimers.clear();
9992        mWifiRunningTimers.clear();
9993        mFullWifiLockTimers.clear();
9994        mWifiScanTimers.clear();
9995        mWifiBatchedScanTimers.clear();
9996        mWifiMulticastTimers.clear();
9997        mAudioTurnedOnTimers.clear();
9998        mVideoTurnedOnTimers.clear();
9999        mFlashlightTurnedOnTimers.clear();
10000        mCameraTurnedOnTimers.clear();
10001
10002        int numUids = in.readInt();
10003        mUidStats.clear();
10004        for (int i = 0; i < numUids; i++) {
10005            int uid = in.readInt();
10006            Uid u = new Uid(uid);
10007            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
10008            mUidStats.append(uid, u);
10009        }
10010    }
10011
10012    public void writeToParcel(Parcel out, int flags) {
10013        writeToParcelLocked(out, true, flags);
10014    }
10015
10016    public void writeToParcelWithoutUids(Parcel out, int flags) {
10017        writeToParcelLocked(out, false, flags);
10018    }
10019
10020    @SuppressWarnings("unused")
10021    void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
10022        // Need to update with current kernel wake lock counts.
10023        pullPendingStateUpdatesLocked();
10024
10025        // Pull the clock time.  This may update the time and make a new history entry
10026        // if we had originally pulled a time before the RTC was set.
10027        long startClockTime = getStartClockTime();
10028
10029        final long uSecUptime = SystemClock.uptimeMillis() * 1000;
10030        final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
10031        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
10032        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
10033
10034        out.writeInt(MAGIC);
10035
10036        writeHistory(out, true, false);
10037
10038        out.writeInt(mStartCount);
10039        out.writeLong(startClockTime);
10040        out.writeString(mStartPlatformVersion);
10041        out.writeString(mEndPlatformVersion);
10042        out.writeLong(mUptime);
10043        out.writeLong(mUptimeStart);
10044        out.writeLong(mRealtime);
10045        out.writeLong(mRealtimeStart);
10046        out.writeInt(mOnBattery ? 1 : 0);
10047        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
10048        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
10049
10050        mScreenOnTimer.writeToParcel(out, uSecRealtime);
10051        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10052            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
10053        }
10054        mInteractiveTimer.writeToParcel(out, uSecRealtime);
10055        mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
10056        mDeviceIdleModeEnabledTimer.writeToParcel(out, uSecRealtime);
10057        mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
10058        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
10059        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10060            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
10061        }
10062        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
10063        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10064            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
10065        }
10066        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
10067            mNetworkByteActivityCounters[i].writeToParcel(out);
10068            mNetworkPacketActivityCounters[i].writeToParcel(out);
10069        }
10070        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
10071        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
10072        mMobileRadioActiveAdjustedTime.writeToParcel(out);
10073        mMobileRadioActiveUnknownTime.writeToParcel(out);
10074        mMobileRadioActiveUnknownCount.writeToParcel(out);
10075        mWifiOnTimer.writeToParcel(out, uSecRealtime);
10076        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
10077        for (int i=0; i<NUM_WIFI_STATES; i++) {
10078            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
10079        }
10080        for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10081            mWifiSupplStateTimer[i].writeToParcel(out, uSecRealtime);
10082        }
10083        for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10084            mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
10085        }
10086        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
10087            mBluetoothActivityCounters[i].writeToParcel(out);
10088        }
10089        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
10090            mWifiActivityCounters[i].writeToParcel(out);
10091        }
10092        out.writeInt(mHasWifiEnergyReporting ? 1 : 0);
10093        out.writeInt(mHasBluetoothEnergyReporting ? 1 : 0);
10094        out.writeInt(mNumConnectivityChange);
10095        out.writeInt(mLoadedNumConnectivityChange);
10096        out.writeInt(mUnpluggedNumConnectivityChange);
10097        mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
10098        mCameraOnTimer.writeToParcel(out, uSecRealtime);
10099        out.writeInt(mDischargeUnplugLevel);
10100        out.writeInt(mDischargePlugLevel);
10101        out.writeInt(mDischargeCurrentLevel);
10102        out.writeInt(mCurrentBatteryLevel);
10103        out.writeInt(mLowDischargeAmountSinceCharge);
10104        out.writeInt(mHighDischargeAmountSinceCharge);
10105        out.writeInt(mDischargeAmountScreenOn);
10106        out.writeInt(mDischargeAmountScreenOnSinceCharge);
10107        out.writeInt(mDischargeAmountScreenOff);
10108        out.writeInt(mDischargeAmountScreenOffSinceCharge);
10109        mDischargeStepTracker.writeToParcel(out);
10110        mChargeStepTracker.writeToParcel(out);
10111        out.writeLong(mLastWriteTime);
10112
10113        if (inclUids) {
10114            out.writeInt(mKernelWakelockStats.size());
10115            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
10116                SamplingTimer kwlt = ent.getValue();
10117                if (kwlt != null) {
10118                    out.writeInt(1);
10119                    out.writeString(ent.getKey());
10120                    kwlt.writeToParcel(out, uSecRealtime);
10121                } else {
10122                    out.writeInt(0);
10123                }
10124            }
10125            out.writeInt(mWakeupReasonStats.size());
10126            for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
10127                SamplingTimer timer = ent.getValue();
10128                if (timer != null) {
10129                    out.writeInt(1);
10130                    out.writeString(ent.getKey());
10131                    timer.writeToParcel(out, uSecRealtime);
10132                } else {
10133                    out.writeInt(0);
10134                }
10135            }
10136        } else {
10137            out.writeInt(0);
10138        }
10139
10140        if (inclUids) {
10141            int size = mUidStats.size();
10142            out.writeInt(size);
10143            for (int i = 0; i < size; i++) {
10144                out.writeInt(mUidStats.keyAt(i));
10145                Uid uid = mUidStats.valueAt(i);
10146
10147                uid.writeToParcelLocked(out, uSecRealtime);
10148            }
10149        } else {
10150            out.writeInt(0);
10151        }
10152    }
10153
10154    public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
10155        new Parcelable.Creator<BatteryStatsImpl>() {
10156        public BatteryStatsImpl createFromParcel(Parcel in) {
10157            return new BatteryStatsImpl(in);
10158        }
10159
10160        public BatteryStatsImpl[] newArray(int size) {
10161            return new BatteryStatsImpl[size];
10162        }
10163    };
10164
10165    public void prepareForDumpLocked() {
10166        // Need to retrieve current kernel wake lock stats before printing.
10167        pullPendingStateUpdatesLocked();
10168
10169        // Pull the clock time.  This may update the time and make a new history entry
10170        // if we had originally pulled a time before the RTC was set.
10171        getStartClockTime();
10172    }
10173
10174    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
10175        if (DEBUG) {
10176            pw.println("mOnBatteryTimeBase:");
10177            mOnBatteryTimeBase.dump(pw, "  ");
10178            pw.println("mOnBatteryScreenOffTimeBase:");
10179            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
10180            Printer pr = new PrintWriterPrinter(pw);
10181            pr.println("*** Screen timer:");
10182            mScreenOnTimer.logState(pr, "  ");
10183            for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
10184                pr.println("*** Screen brightness #" + i + ":");
10185                mScreenBrightnessTimer[i].logState(pr, "  ");
10186            }
10187            pr.println("*** Interactive timer:");
10188            mInteractiveTimer.logState(pr, "  ");
10189            pr.println("*** Power save mode timer:");
10190            mPowerSaveModeEnabledTimer.logState(pr, "  ");
10191            pr.println("*** Device idle mode timer:");
10192            mDeviceIdleModeEnabledTimer.logState(pr, "  ");
10193            pr.println("*** Device idling timer:");
10194            mDeviceIdlingTimer.logState(pr, "  ");
10195            pr.println("*** Phone timer:");
10196            mPhoneOnTimer.logState(pr, "  ");
10197            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
10198                pr.println("*** Phone signal strength #" + i + ":");
10199                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
10200            }
10201            pr.println("*** Signal scanning :");
10202            mPhoneSignalScanningTimer.logState(pr, "  ");
10203            for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
10204                pr.println("*** Data connection type #" + i + ":");
10205                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
10206            }
10207            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
10208            pr.println("*** Mobile network active timer:");
10209            mMobileRadioActiveTimer.logState(pr, "  ");
10210            pr.println("*** Mobile network active adjusted timer:");
10211            mMobileRadioActiveAdjustedTime.logState(pr, "  ");
10212            pr.println("*** mWifiRadioPowerState=" + mWifiRadioPowerState);
10213            pr.println("*** Wifi timer:");
10214            mWifiOnTimer.logState(pr, "  ");
10215            pr.println("*** WifiRunning timer:");
10216            mGlobalWifiRunningTimer.logState(pr, "  ");
10217            for (int i=0; i<NUM_WIFI_STATES; i++) {
10218                pr.println("*** Wifi state #" + i + ":");
10219                mWifiStateTimer[i].logState(pr, "  ");
10220            }
10221            for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
10222                pr.println("*** Wifi suppl state #" + i + ":");
10223                mWifiSupplStateTimer[i].logState(pr, "  ");
10224            }
10225            for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
10226                pr.println("*** Wifi signal strength #" + i + ":");
10227                mWifiSignalStrengthsTimer[i].logState(pr, "  ");
10228            }
10229            pr.println("*** Flashlight timer:");
10230            mFlashlightOnTimer.logState(pr, "  ");
10231            pr.println("*** Camera timer:");
10232            mCameraOnTimer.logState(pr, "  ");
10233        }
10234        super.dumpLocked(context, pw, flags, reqUid, histStart);
10235    }
10236}
10237