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