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