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