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