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